cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

stm32-timer-cnt.c (10970B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * STM32 Timer Encoder and Counter driver
      4 *
      5 * Copyright (C) STMicroelectronics 2018
      6 *
      7 * Author: Benjamin Gaignard <benjamin.gaignard@st.com>
      8 *
      9 */
     10#include <linux/counter.h>
     11#include <linux/mfd/stm32-timers.h>
     12#include <linux/mod_devicetable.h>
     13#include <linux/module.h>
     14#include <linux/pinctrl/consumer.h>
     15#include <linux/platform_device.h>
     16#include <linux/types.h>
     17
     18#define TIM_CCMR_CCXS	(BIT(8) | BIT(0))
     19#define TIM_CCMR_MASK	(TIM_CCMR_CC1S | TIM_CCMR_CC2S | \
     20			 TIM_CCMR_IC1F | TIM_CCMR_IC2F)
     21#define TIM_CCER_MASK	(TIM_CCER_CC1P | TIM_CCER_CC1NP | \
     22			 TIM_CCER_CC2P | TIM_CCER_CC2NP)
     23
     24struct stm32_timer_regs {
     25	u32 cr1;
     26	u32 cnt;
     27	u32 smcr;
     28	u32 arr;
     29};
     30
     31struct stm32_timer_cnt {
     32	struct regmap *regmap;
     33	struct clk *clk;
     34	u32 max_arr;
     35	bool enabled;
     36	struct stm32_timer_regs bak;
     37};
     38
     39static const enum counter_function stm32_count_functions[] = {
     40	COUNTER_FUNCTION_INCREASE,
     41	COUNTER_FUNCTION_QUADRATURE_X2_A,
     42	COUNTER_FUNCTION_QUADRATURE_X2_B,
     43	COUNTER_FUNCTION_QUADRATURE_X4,
     44};
     45
     46static int stm32_count_read(struct counter_device *counter,
     47			    struct counter_count *count, u64 *val)
     48{
     49	struct stm32_timer_cnt *const priv = counter_priv(counter);
     50	u32 cnt;
     51
     52	regmap_read(priv->regmap, TIM_CNT, &cnt);
     53	*val = cnt;
     54
     55	return 0;
     56}
     57
     58static int stm32_count_write(struct counter_device *counter,
     59			     struct counter_count *count, const u64 val)
     60{
     61	struct stm32_timer_cnt *const priv = counter_priv(counter);
     62	u32 ceiling;
     63
     64	regmap_read(priv->regmap, TIM_ARR, &ceiling);
     65	if (val > ceiling)
     66		return -EINVAL;
     67
     68	return regmap_write(priv->regmap, TIM_CNT, val);
     69}
     70
     71static int stm32_count_function_read(struct counter_device *counter,
     72				     struct counter_count *count,
     73				     enum counter_function *function)
     74{
     75	struct stm32_timer_cnt *const priv = counter_priv(counter);
     76	u32 smcr;
     77
     78	regmap_read(priv->regmap, TIM_SMCR, &smcr);
     79
     80	switch (smcr & TIM_SMCR_SMS) {
     81	case TIM_SMCR_SMS_SLAVE_MODE_DISABLED:
     82		*function = COUNTER_FUNCTION_INCREASE;
     83		return 0;
     84	case TIM_SMCR_SMS_ENCODER_MODE_1:
     85		*function = COUNTER_FUNCTION_QUADRATURE_X2_A;
     86		return 0;
     87	case TIM_SMCR_SMS_ENCODER_MODE_2:
     88		*function = COUNTER_FUNCTION_QUADRATURE_X2_B;
     89		return 0;
     90	case TIM_SMCR_SMS_ENCODER_MODE_3:
     91		*function = COUNTER_FUNCTION_QUADRATURE_X4;
     92		return 0;
     93	default:
     94		return -EINVAL;
     95	}
     96}
     97
     98static int stm32_count_function_write(struct counter_device *counter,
     99				      struct counter_count *count,
    100				      enum counter_function function)
    101{
    102	struct stm32_timer_cnt *const priv = counter_priv(counter);
    103	u32 cr1, sms;
    104
    105	switch (function) {
    106	case COUNTER_FUNCTION_INCREASE:
    107		sms = TIM_SMCR_SMS_SLAVE_MODE_DISABLED;
    108		break;
    109	case COUNTER_FUNCTION_QUADRATURE_X2_A:
    110		sms = TIM_SMCR_SMS_ENCODER_MODE_1;
    111		break;
    112	case COUNTER_FUNCTION_QUADRATURE_X2_B:
    113		sms = TIM_SMCR_SMS_ENCODER_MODE_2;
    114		break;
    115	case COUNTER_FUNCTION_QUADRATURE_X4:
    116		sms = TIM_SMCR_SMS_ENCODER_MODE_3;
    117		break;
    118	default:
    119		return -EINVAL;
    120	}
    121
    122	/* Store enable status */
    123	regmap_read(priv->regmap, TIM_CR1, &cr1);
    124
    125	regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0);
    126
    127	regmap_update_bits(priv->regmap, TIM_SMCR, TIM_SMCR_SMS, sms);
    128
    129	/* Make sure that registers are updated */
    130	regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG);
    131
    132	/* Restore the enable status */
    133	regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, cr1);
    134
    135	return 0;
    136}
    137
    138static int stm32_count_direction_read(struct counter_device *counter,
    139				      struct counter_count *count,
    140				      enum counter_count_direction *direction)
    141{
    142	struct stm32_timer_cnt *const priv = counter_priv(counter);
    143	u32 cr1;
    144
    145	regmap_read(priv->regmap, TIM_CR1, &cr1);
    146	*direction = (cr1 & TIM_CR1_DIR) ? COUNTER_COUNT_DIRECTION_BACKWARD :
    147		COUNTER_COUNT_DIRECTION_FORWARD;
    148
    149	return 0;
    150}
    151
    152static int stm32_count_ceiling_read(struct counter_device *counter,
    153				    struct counter_count *count, u64 *ceiling)
    154{
    155	struct stm32_timer_cnt *const priv = counter_priv(counter);
    156	u32 arr;
    157
    158	regmap_read(priv->regmap, TIM_ARR, &arr);
    159
    160	*ceiling = arr;
    161
    162	return 0;
    163}
    164
    165static int stm32_count_ceiling_write(struct counter_device *counter,
    166				     struct counter_count *count, u64 ceiling)
    167{
    168	struct stm32_timer_cnt *const priv = counter_priv(counter);
    169
    170	if (ceiling > priv->max_arr)
    171		return -ERANGE;
    172
    173	/* TIMx_ARR register shouldn't be buffered (ARPE=0) */
    174	regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, 0);
    175	regmap_write(priv->regmap, TIM_ARR, ceiling);
    176
    177	return 0;
    178}
    179
    180static int stm32_count_enable_read(struct counter_device *counter,
    181				   struct counter_count *count, u8 *enable)
    182{
    183	struct stm32_timer_cnt *const priv = counter_priv(counter);
    184	u32 cr1;
    185
    186	regmap_read(priv->regmap, TIM_CR1, &cr1);
    187
    188	*enable = cr1 & TIM_CR1_CEN;
    189
    190	return 0;
    191}
    192
    193static int stm32_count_enable_write(struct counter_device *counter,
    194				    struct counter_count *count, u8 enable)
    195{
    196	struct stm32_timer_cnt *const priv = counter_priv(counter);
    197	u32 cr1;
    198
    199	if (enable) {
    200		regmap_read(priv->regmap, TIM_CR1, &cr1);
    201		if (!(cr1 & TIM_CR1_CEN))
    202			clk_enable(priv->clk);
    203
    204		regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN,
    205				   TIM_CR1_CEN);
    206	} else {
    207		regmap_read(priv->regmap, TIM_CR1, &cr1);
    208		regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0);
    209		if (cr1 & TIM_CR1_CEN)
    210			clk_disable(priv->clk);
    211	}
    212
    213	/* Keep enabled state to properly handle low power states */
    214	priv->enabled = enable;
    215
    216	return 0;
    217}
    218
    219static struct counter_comp stm32_count_ext[] = {
    220	COUNTER_COMP_DIRECTION(stm32_count_direction_read),
    221	COUNTER_COMP_ENABLE(stm32_count_enable_read, stm32_count_enable_write),
    222	COUNTER_COMP_CEILING(stm32_count_ceiling_read,
    223			     stm32_count_ceiling_write),
    224};
    225
    226static const enum counter_synapse_action stm32_synapse_actions[] = {
    227	COUNTER_SYNAPSE_ACTION_NONE,
    228	COUNTER_SYNAPSE_ACTION_BOTH_EDGES
    229};
    230
    231static int stm32_action_read(struct counter_device *counter,
    232			     struct counter_count *count,
    233			     struct counter_synapse *synapse,
    234			     enum counter_synapse_action *action)
    235{
    236	enum counter_function function;
    237	int err;
    238
    239	err = stm32_count_function_read(counter, count, &function);
    240	if (err)
    241		return err;
    242
    243	switch (function) {
    244	case COUNTER_FUNCTION_INCREASE:
    245		/* counts on internal clock when CEN=1 */
    246		*action = COUNTER_SYNAPSE_ACTION_NONE;
    247		return 0;
    248	case COUNTER_FUNCTION_QUADRATURE_X2_A:
    249		/* counts up/down on TI1FP1 edge depending on TI2FP2 level */
    250		if (synapse->signal->id == count->synapses[0].signal->id)
    251			*action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
    252		else
    253			*action = COUNTER_SYNAPSE_ACTION_NONE;
    254		return 0;
    255	case COUNTER_FUNCTION_QUADRATURE_X2_B:
    256		/* counts up/down on TI2FP2 edge depending on TI1FP1 level */
    257		if (synapse->signal->id == count->synapses[1].signal->id)
    258			*action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
    259		else
    260			*action = COUNTER_SYNAPSE_ACTION_NONE;
    261		return 0;
    262	case COUNTER_FUNCTION_QUADRATURE_X4:
    263		/* counts up/down on both TI1FP1 and TI2FP2 edges */
    264		*action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
    265		return 0;
    266	default:
    267		return -EINVAL;
    268	}
    269}
    270
    271static const struct counter_ops stm32_timer_cnt_ops = {
    272	.count_read = stm32_count_read,
    273	.count_write = stm32_count_write,
    274	.function_read = stm32_count_function_read,
    275	.function_write = stm32_count_function_write,
    276	.action_read = stm32_action_read,
    277};
    278
    279static struct counter_signal stm32_signals[] = {
    280	{
    281		.id = 0,
    282		.name = "Channel 1 Quadrature A"
    283	},
    284	{
    285		.id = 1,
    286		.name = "Channel 1 Quadrature B"
    287	}
    288};
    289
    290static struct counter_synapse stm32_count_synapses[] = {
    291	{
    292		.actions_list = stm32_synapse_actions,
    293		.num_actions = ARRAY_SIZE(stm32_synapse_actions),
    294		.signal = &stm32_signals[0]
    295	},
    296	{
    297		.actions_list = stm32_synapse_actions,
    298		.num_actions = ARRAY_SIZE(stm32_synapse_actions),
    299		.signal = &stm32_signals[1]
    300	}
    301};
    302
    303static struct counter_count stm32_counts = {
    304	.id = 0,
    305	.name = "Channel 1 Count",
    306	.functions_list = stm32_count_functions,
    307	.num_functions = ARRAY_SIZE(stm32_count_functions),
    308	.synapses = stm32_count_synapses,
    309	.num_synapses = ARRAY_SIZE(stm32_count_synapses),
    310	.ext = stm32_count_ext,
    311	.num_ext = ARRAY_SIZE(stm32_count_ext)
    312};
    313
    314static int stm32_timer_cnt_probe(struct platform_device *pdev)
    315{
    316	struct stm32_timers *ddata = dev_get_drvdata(pdev->dev.parent);
    317	struct device *dev = &pdev->dev;
    318	struct stm32_timer_cnt *priv;
    319	struct counter_device *counter;
    320	int ret;
    321
    322	if (IS_ERR_OR_NULL(ddata))
    323		return -EINVAL;
    324
    325	counter = devm_counter_alloc(dev, sizeof(*priv));
    326	if (!counter)
    327		return -ENOMEM;
    328
    329	priv = counter_priv(counter);
    330
    331	priv->regmap = ddata->regmap;
    332	priv->clk = ddata->clk;
    333	priv->max_arr = ddata->max_arr;
    334
    335	counter->name = dev_name(dev);
    336	counter->parent = dev;
    337	counter->ops = &stm32_timer_cnt_ops;
    338	counter->counts = &stm32_counts;
    339	counter->num_counts = 1;
    340	counter->signals = stm32_signals;
    341	counter->num_signals = ARRAY_SIZE(stm32_signals);
    342
    343	platform_set_drvdata(pdev, priv);
    344
    345	/* Register Counter device */
    346	ret = devm_counter_add(dev, counter);
    347	if (ret < 0)
    348		dev_err_probe(dev, ret, "Failed to add counter\n");
    349
    350	return ret;
    351}
    352
    353static int __maybe_unused stm32_timer_cnt_suspend(struct device *dev)
    354{
    355	struct stm32_timer_cnt *priv = dev_get_drvdata(dev);
    356
    357	/* Only take care of enabled counter: don't disturb other MFD child */
    358	if (priv->enabled) {
    359		/* Backup registers that may get lost in low power mode */
    360		regmap_read(priv->regmap, TIM_SMCR, &priv->bak.smcr);
    361		regmap_read(priv->regmap, TIM_ARR, &priv->bak.arr);
    362		regmap_read(priv->regmap, TIM_CNT, &priv->bak.cnt);
    363		regmap_read(priv->regmap, TIM_CR1, &priv->bak.cr1);
    364
    365		/* Disable the counter */
    366		regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0);
    367		clk_disable(priv->clk);
    368	}
    369
    370	return pinctrl_pm_select_sleep_state(dev);
    371}
    372
    373static int __maybe_unused stm32_timer_cnt_resume(struct device *dev)
    374{
    375	struct stm32_timer_cnt *priv = dev_get_drvdata(dev);
    376	int ret;
    377
    378	ret = pinctrl_pm_select_default_state(dev);
    379	if (ret)
    380		return ret;
    381
    382	if (priv->enabled) {
    383		clk_enable(priv->clk);
    384
    385		/* Restore registers that may have been lost */
    386		regmap_write(priv->regmap, TIM_SMCR, priv->bak.smcr);
    387		regmap_write(priv->regmap, TIM_ARR, priv->bak.arr);
    388		regmap_write(priv->regmap, TIM_CNT, priv->bak.cnt);
    389
    390		/* Also re-enables the counter */
    391		regmap_write(priv->regmap, TIM_CR1, priv->bak.cr1);
    392	}
    393
    394	return 0;
    395}
    396
    397static SIMPLE_DEV_PM_OPS(stm32_timer_cnt_pm_ops, stm32_timer_cnt_suspend,
    398			 stm32_timer_cnt_resume);
    399
    400static const struct of_device_id stm32_timer_cnt_of_match[] = {
    401	{ .compatible = "st,stm32-timer-counter", },
    402	{},
    403};
    404MODULE_DEVICE_TABLE(of, stm32_timer_cnt_of_match);
    405
    406static struct platform_driver stm32_timer_cnt_driver = {
    407	.probe = stm32_timer_cnt_probe,
    408	.driver = {
    409		.name = "stm32-timer-counter",
    410		.of_match_table = stm32_timer_cnt_of_match,
    411		.pm = &stm32_timer_cnt_pm_ops,
    412	},
    413};
    414module_platform_driver(stm32_timer_cnt_driver);
    415
    416MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
    417MODULE_ALIAS("platform:stm32-timer-counter");
    418MODULE_DESCRIPTION("STMicroelectronics STM32 TIMER counter driver");
    419MODULE_LICENSE("GPL v2");