18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * STM32 Timer Encoder and Counter driver
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) STMicroelectronics 2018
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Author: Benjamin Gaignard <benjamin.gaignard@st.com>
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci#include <linux/counter.h>
118c2ecf20Sopenharmony_ci#include <linux/mfd/stm32-timers.h>
128c2ecf20Sopenharmony_ci#include <linux/mod_devicetable.h>
138c2ecf20Sopenharmony_ci#include <linux/module.h>
148c2ecf20Sopenharmony_ci#include <linux/pinctrl/consumer.h>
158c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#define TIM_CCMR_CCXS	(BIT(8) | BIT(0))
188c2ecf20Sopenharmony_ci#define TIM_CCMR_MASK	(TIM_CCMR_CC1S | TIM_CCMR_CC2S | \
198c2ecf20Sopenharmony_ci			 TIM_CCMR_IC1F | TIM_CCMR_IC2F)
208c2ecf20Sopenharmony_ci#define TIM_CCER_MASK	(TIM_CCER_CC1P | TIM_CCER_CC1NP | \
218c2ecf20Sopenharmony_ci			 TIM_CCER_CC2P | TIM_CCER_CC2NP)
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_cistruct stm32_timer_regs {
248c2ecf20Sopenharmony_ci	u32 cr1;
258c2ecf20Sopenharmony_ci	u32 cnt;
268c2ecf20Sopenharmony_ci	u32 smcr;
278c2ecf20Sopenharmony_ci	u32 arr;
288c2ecf20Sopenharmony_ci};
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_cistruct stm32_timer_cnt {
318c2ecf20Sopenharmony_ci	struct counter_device counter;
328c2ecf20Sopenharmony_ci	struct regmap *regmap;
338c2ecf20Sopenharmony_ci	struct clk *clk;
348c2ecf20Sopenharmony_ci	u32 max_arr;
358c2ecf20Sopenharmony_ci	bool enabled;
368c2ecf20Sopenharmony_ci	struct stm32_timer_regs bak;
378c2ecf20Sopenharmony_ci};
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci/**
408c2ecf20Sopenharmony_ci * enum stm32_count_function - enumerates stm32 timer counter encoder modes
418c2ecf20Sopenharmony_ci * @STM32_COUNT_SLAVE_MODE_DISABLED: counts on internal clock when CEN=1
428c2ecf20Sopenharmony_ci * @STM32_COUNT_ENCODER_MODE_1: counts TI1FP1 edges, depending on TI2FP2 level
438c2ecf20Sopenharmony_ci * @STM32_COUNT_ENCODER_MODE_2: counts TI2FP2 edges, depending on TI1FP1 level
448c2ecf20Sopenharmony_ci * @STM32_COUNT_ENCODER_MODE_3: counts on both TI1FP1 and TI2FP2 edges
458c2ecf20Sopenharmony_ci */
468c2ecf20Sopenharmony_cienum stm32_count_function {
478c2ecf20Sopenharmony_ci	STM32_COUNT_SLAVE_MODE_DISABLED,
488c2ecf20Sopenharmony_ci	STM32_COUNT_ENCODER_MODE_1,
498c2ecf20Sopenharmony_ci	STM32_COUNT_ENCODER_MODE_2,
508c2ecf20Sopenharmony_ci	STM32_COUNT_ENCODER_MODE_3,
518c2ecf20Sopenharmony_ci};
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_cistatic enum counter_count_function stm32_count_functions[] = {
548c2ecf20Sopenharmony_ci	[STM32_COUNT_SLAVE_MODE_DISABLED] = COUNTER_COUNT_FUNCTION_INCREASE,
558c2ecf20Sopenharmony_ci	[STM32_COUNT_ENCODER_MODE_1] = COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A,
568c2ecf20Sopenharmony_ci	[STM32_COUNT_ENCODER_MODE_2] = COUNTER_COUNT_FUNCTION_QUADRATURE_X2_B,
578c2ecf20Sopenharmony_ci	[STM32_COUNT_ENCODER_MODE_3] = COUNTER_COUNT_FUNCTION_QUADRATURE_X4,
588c2ecf20Sopenharmony_ci};
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_cistatic int stm32_count_read(struct counter_device *counter,
618c2ecf20Sopenharmony_ci			    struct counter_count *count, unsigned long *val)
628c2ecf20Sopenharmony_ci{
638c2ecf20Sopenharmony_ci	struct stm32_timer_cnt *const priv = counter->priv;
648c2ecf20Sopenharmony_ci	u32 cnt;
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	regmap_read(priv->regmap, TIM_CNT, &cnt);
678c2ecf20Sopenharmony_ci	*val = cnt;
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	return 0;
708c2ecf20Sopenharmony_ci}
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_cistatic int stm32_count_write(struct counter_device *counter,
738c2ecf20Sopenharmony_ci			     struct counter_count *count,
748c2ecf20Sopenharmony_ci			     const unsigned long val)
758c2ecf20Sopenharmony_ci{
768c2ecf20Sopenharmony_ci	struct stm32_timer_cnt *const priv = counter->priv;
778c2ecf20Sopenharmony_ci	u32 ceiling;
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	regmap_read(priv->regmap, TIM_ARR, &ceiling);
808c2ecf20Sopenharmony_ci	if (val > ceiling)
818c2ecf20Sopenharmony_ci		return -EINVAL;
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	return regmap_write(priv->regmap, TIM_CNT, val);
848c2ecf20Sopenharmony_ci}
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_cistatic int stm32_count_function_get(struct counter_device *counter,
878c2ecf20Sopenharmony_ci				    struct counter_count *count,
888c2ecf20Sopenharmony_ci				    size_t *function)
898c2ecf20Sopenharmony_ci{
908c2ecf20Sopenharmony_ci	struct stm32_timer_cnt *const priv = counter->priv;
918c2ecf20Sopenharmony_ci	u32 smcr;
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	regmap_read(priv->regmap, TIM_SMCR, &smcr);
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	switch (smcr & TIM_SMCR_SMS) {
968c2ecf20Sopenharmony_ci	case 0:
978c2ecf20Sopenharmony_ci		*function = STM32_COUNT_SLAVE_MODE_DISABLED;
988c2ecf20Sopenharmony_ci		return 0;
998c2ecf20Sopenharmony_ci	case 1:
1008c2ecf20Sopenharmony_ci		*function = STM32_COUNT_ENCODER_MODE_1;
1018c2ecf20Sopenharmony_ci		return 0;
1028c2ecf20Sopenharmony_ci	case 2:
1038c2ecf20Sopenharmony_ci		*function = STM32_COUNT_ENCODER_MODE_2;
1048c2ecf20Sopenharmony_ci		return 0;
1058c2ecf20Sopenharmony_ci	case 3:
1068c2ecf20Sopenharmony_ci		*function = STM32_COUNT_ENCODER_MODE_3;
1078c2ecf20Sopenharmony_ci		return 0;
1088c2ecf20Sopenharmony_ci	default:
1098c2ecf20Sopenharmony_ci		return -EINVAL;
1108c2ecf20Sopenharmony_ci	}
1118c2ecf20Sopenharmony_ci}
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_cistatic int stm32_count_function_set(struct counter_device *counter,
1148c2ecf20Sopenharmony_ci				    struct counter_count *count,
1158c2ecf20Sopenharmony_ci				    size_t function)
1168c2ecf20Sopenharmony_ci{
1178c2ecf20Sopenharmony_ci	struct stm32_timer_cnt *const priv = counter->priv;
1188c2ecf20Sopenharmony_ci	u32 cr1, sms;
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	switch (function) {
1218c2ecf20Sopenharmony_ci	case STM32_COUNT_SLAVE_MODE_DISABLED:
1228c2ecf20Sopenharmony_ci		sms = 0;
1238c2ecf20Sopenharmony_ci		break;
1248c2ecf20Sopenharmony_ci	case STM32_COUNT_ENCODER_MODE_1:
1258c2ecf20Sopenharmony_ci		sms = 1;
1268c2ecf20Sopenharmony_ci		break;
1278c2ecf20Sopenharmony_ci	case STM32_COUNT_ENCODER_MODE_2:
1288c2ecf20Sopenharmony_ci		sms = 2;
1298c2ecf20Sopenharmony_ci		break;
1308c2ecf20Sopenharmony_ci	case STM32_COUNT_ENCODER_MODE_3:
1318c2ecf20Sopenharmony_ci		sms = 3;
1328c2ecf20Sopenharmony_ci		break;
1338c2ecf20Sopenharmony_ci	default:
1348c2ecf20Sopenharmony_ci		return -EINVAL;
1358c2ecf20Sopenharmony_ci	}
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	/* Store enable status */
1388c2ecf20Sopenharmony_ci	regmap_read(priv->regmap, TIM_CR1, &cr1);
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0);
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	regmap_update_bits(priv->regmap, TIM_SMCR, TIM_SMCR_SMS, sms);
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	/* Make sure that registers are updated */
1458c2ecf20Sopenharmony_ci	regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG);
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	/* Restore the enable status */
1488c2ecf20Sopenharmony_ci	regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, cr1);
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	return 0;
1518c2ecf20Sopenharmony_ci}
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_cistatic ssize_t stm32_count_direction_read(struct counter_device *counter,
1548c2ecf20Sopenharmony_ci				      struct counter_count *count,
1558c2ecf20Sopenharmony_ci				      void *private, char *buf)
1568c2ecf20Sopenharmony_ci{
1578c2ecf20Sopenharmony_ci	struct stm32_timer_cnt *const priv = counter->priv;
1588c2ecf20Sopenharmony_ci	const char *direction;
1598c2ecf20Sopenharmony_ci	u32 cr1;
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	regmap_read(priv->regmap, TIM_CR1, &cr1);
1628c2ecf20Sopenharmony_ci	direction = (cr1 & TIM_CR1_DIR) ? "backward" : "forward";
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci	return scnprintf(buf, PAGE_SIZE, "%s\n", direction);
1658c2ecf20Sopenharmony_ci}
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_cistatic ssize_t stm32_count_ceiling_read(struct counter_device *counter,
1688c2ecf20Sopenharmony_ci					struct counter_count *count,
1698c2ecf20Sopenharmony_ci					void *private, char *buf)
1708c2ecf20Sopenharmony_ci{
1718c2ecf20Sopenharmony_ci	struct stm32_timer_cnt *const priv = counter->priv;
1728c2ecf20Sopenharmony_ci	u32 arr;
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	regmap_read(priv->regmap, TIM_ARR, &arr);
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%u\n", arr);
1778c2ecf20Sopenharmony_ci}
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_cistatic ssize_t stm32_count_ceiling_write(struct counter_device *counter,
1808c2ecf20Sopenharmony_ci					 struct counter_count *count,
1818c2ecf20Sopenharmony_ci					 void *private,
1828c2ecf20Sopenharmony_ci					 const char *buf, size_t len)
1838c2ecf20Sopenharmony_ci{
1848c2ecf20Sopenharmony_ci	struct stm32_timer_cnt *const priv = counter->priv;
1858c2ecf20Sopenharmony_ci	unsigned int ceiling;
1868c2ecf20Sopenharmony_ci	int ret;
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	ret = kstrtouint(buf, 0, &ceiling);
1898c2ecf20Sopenharmony_ci	if (ret)
1908c2ecf20Sopenharmony_ci		return ret;
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	if (ceiling > priv->max_arr)
1938c2ecf20Sopenharmony_ci		return -ERANGE;
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	/* TIMx_ARR register shouldn't be buffered (ARPE=0) */
1968c2ecf20Sopenharmony_ci	regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, 0);
1978c2ecf20Sopenharmony_ci	regmap_write(priv->regmap, TIM_ARR, ceiling);
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	return len;
2008c2ecf20Sopenharmony_ci}
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_cistatic ssize_t stm32_count_enable_read(struct counter_device *counter,
2038c2ecf20Sopenharmony_ci				       struct counter_count *count,
2048c2ecf20Sopenharmony_ci				       void *private, char *buf)
2058c2ecf20Sopenharmony_ci{
2068c2ecf20Sopenharmony_ci	struct stm32_timer_cnt *const priv = counter->priv;
2078c2ecf20Sopenharmony_ci	u32 cr1;
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	regmap_read(priv->regmap, TIM_CR1, &cr1);
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci	return scnprintf(buf, PAGE_SIZE, "%d\n", (bool)(cr1 & TIM_CR1_CEN));
2128c2ecf20Sopenharmony_ci}
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_cistatic ssize_t stm32_count_enable_write(struct counter_device *counter,
2158c2ecf20Sopenharmony_ci					struct counter_count *count,
2168c2ecf20Sopenharmony_ci					void *private,
2178c2ecf20Sopenharmony_ci					const char *buf, size_t len)
2188c2ecf20Sopenharmony_ci{
2198c2ecf20Sopenharmony_ci	struct stm32_timer_cnt *const priv = counter->priv;
2208c2ecf20Sopenharmony_ci	int err;
2218c2ecf20Sopenharmony_ci	u32 cr1;
2228c2ecf20Sopenharmony_ci	bool enable;
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	err = kstrtobool(buf, &enable);
2258c2ecf20Sopenharmony_ci	if (err)
2268c2ecf20Sopenharmony_ci		return err;
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	if (enable) {
2298c2ecf20Sopenharmony_ci		regmap_read(priv->regmap, TIM_CR1, &cr1);
2308c2ecf20Sopenharmony_ci		if (!(cr1 & TIM_CR1_CEN))
2318c2ecf20Sopenharmony_ci			clk_enable(priv->clk);
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci		regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN,
2348c2ecf20Sopenharmony_ci				   TIM_CR1_CEN);
2358c2ecf20Sopenharmony_ci	} else {
2368c2ecf20Sopenharmony_ci		regmap_read(priv->regmap, TIM_CR1, &cr1);
2378c2ecf20Sopenharmony_ci		regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0);
2388c2ecf20Sopenharmony_ci		if (cr1 & TIM_CR1_CEN)
2398c2ecf20Sopenharmony_ci			clk_disable(priv->clk);
2408c2ecf20Sopenharmony_ci	}
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	/* Keep enabled state to properly handle low power states */
2438c2ecf20Sopenharmony_ci	priv->enabled = enable;
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	return len;
2468c2ecf20Sopenharmony_ci}
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_cistatic const struct counter_count_ext stm32_count_ext[] = {
2498c2ecf20Sopenharmony_ci	{
2508c2ecf20Sopenharmony_ci		.name = "direction",
2518c2ecf20Sopenharmony_ci		.read = stm32_count_direction_read,
2528c2ecf20Sopenharmony_ci	},
2538c2ecf20Sopenharmony_ci	{
2548c2ecf20Sopenharmony_ci		.name = "enable",
2558c2ecf20Sopenharmony_ci		.read = stm32_count_enable_read,
2568c2ecf20Sopenharmony_ci		.write = stm32_count_enable_write
2578c2ecf20Sopenharmony_ci	},
2588c2ecf20Sopenharmony_ci	{
2598c2ecf20Sopenharmony_ci		.name = "ceiling",
2608c2ecf20Sopenharmony_ci		.read = stm32_count_ceiling_read,
2618c2ecf20Sopenharmony_ci		.write = stm32_count_ceiling_write
2628c2ecf20Sopenharmony_ci	},
2638c2ecf20Sopenharmony_ci};
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_cienum stm32_synapse_action {
2668c2ecf20Sopenharmony_ci	STM32_SYNAPSE_ACTION_NONE,
2678c2ecf20Sopenharmony_ci	STM32_SYNAPSE_ACTION_BOTH_EDGES
2688c2ecf20Sopenharmony_ci};
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_cistatic enum counter_synapse_action stm32_synapse_actions[] = {
2718c2ecf20Sopenharmony_ci	[STM32_SYNAPSE_ACTION_NONE] = COUNTER_SYNAPSE_ACTION_NONE,
2728c2ecf20Sopenharmony_ci	[STM32_SYNAPSE_ACTION_BOTH_EDGES] = COUNTER_SYNAPSE_ACTION_BOTH_EDGES
2738c2ecf20Sopenharmony_ci};
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_cistatic int stm32_action_get(struct counter_device *counter,
2768c2ecf20Sopenharmony_ci			    struct counter_count *count,
2778c2ecf20Sopenharmony_ci			    struct counter_synapse *synapse,
2788c2ecf20Sopenharmony_ci			    size_t *action)
2798c2ecf20Sopenharmony_ci{
2808c2ecf20Sopenharmony_ci	size_t function;
2818c2ecf20Sopenharmony_ci	int err;
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci	err = stm32_count_function_get(counter, count, &function);
2848c2ecf20Sopenharmony_ci	if (err)
2858c2ecf20Sopenharmony_ci		return err;
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	switch (function) {
2888c2ecf20Sopenharmony_ci	case STM32_COUNT_SLAVE_MODE_DISABLED:
2898c2ecf20Sopenharmony_ci		/* counts on internal clock when CEN=1 */
2908c2ecf20Sopenharmony_ci		*action = STM32_SYNAPSE_ACTION_NONE;
2918c2ecf20Sopenharmony_ci		return 0;
2928c2ecf20Sopenharmony_ci	case STM32_COUNT_ENCODER_MODE_1:
2938c2ecf20Sopenharmony_ci		/* counts up/down on TI1FP1 edge depending on TI2FP2 level */
2948c2ecf20Sopenharmony_ci		if (synapse->signal->id == count->synapses[0].signal->id)
2958c2ecf20Sopenharmony_ci			*action = STM32_SYNAPSE_ACTION_BOTH_EDGES;
2968c2ecf20Sopenharmony_ci		else
2978c2ecf20Sopenharmony_ci			*action = STM32_SYNAPSE_ACTION_NONE;
2988c2ecf20Sopenharmony_ci		return 0;
2998c2ecf20Sopenharmony_ci	case STM32_COUNT_ENCODER_MODE_2:
3008c2ecf20Sopenharmony_ci		/* counts up/down on TI2FP2 edge depending on TI1FP1 level */
3018c2ecf20Sopenharmony_ci		if (synapse->signal->id == count->synapses[1].signal->id)
3028c2ecf20Sopenharmony_ci			*action = STM32_SYNAPSE_ACTION_BOTH_EDGES;
3038c2ecf20Sopenharmony_ci		else
3048c2ecf20Sopenharmony_ci			*action = STM32_SYNAPSE_ACTION_NONE;
3058c2ecf20Sopenharmony_ci		return 0;
3068c2ecf20Sopenharmony_ci	case STM32_COUNT_ENCODER_MODE_3:
3078c2ecf20Sopenharmony_ci		/* counts up/down on both TI1FP1 and TI2FP2 edges */
3088c2ecf20Sopenharmony_ci		*action = STM32_SYNAPSE_ACTION_BOTH_EDGES;
3098c2ecf20Sopenharmony_ci		return 0;
3108c2ecf20Sopenharmony_ci	default:
3118c2ecf20Sopenharmony_ci		return -EINVAL;
3128c2ecf20Sopenharmony_ci	}
3138c2ecf20Sopenharmony_ci}
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_cistatic const struct counter_ops stm32_timer_cnt_ops = {
3168c2ecf20Sopenharmony_ci	.count_read = stm32_count_read,
3178c2ecf20Sopenharmony_ci	.count_write = stm32_count_write,
3188c2ecf20Sopenharmony_ci	.function_get = stm32_count_function_get,
3198c2ecf20Sopenharmony_ci	.function_set = stm32_count_function_set,
3208c2ecf20Sopenharmony_ci	.action_get = stm32_action_get,
3218c2ecf20Sopenharmony_ci};
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_cistatic struct counter_signal stm32_signals[] = {
3248c2ecf20Sopenharmony_ci	{
3258c2ecf20Sopenharmony_ci		.id = 0,
3268c2ecf20Sopenharmony_ci		.name = "Channel 1 Quadrature A"
3278c2ecf20Sopenharmony_ci	},
3288c2ecf20Sopenharmony_ci	{
3298c2ecf20Sopenharmony_ci		.id = 1,
3308c2ecf20Sopenharmony_ci		.name = "Channel 1 Quadrature B"
3318c2ecf20Sopenharmony_ci	}
3328c2ecf20Sopenharmony_ci};
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_cistatic struct counter_synapse stm32_count_synapses[] = {
3358c2ecf20Sopenharmony_ci	{
3368c2ecf20Sopenharmony_ci		.actions_list = stm32_synapse_actions,
3378c2ecf20Sopenharmony_ci		.num_actions = ARRAY_SIZE(stm32_synapse_actions),
3388c2ecf20Sopenharmony_ci		.signal = &stm32_signals[0]
3398c2ecf20Sopenharmony_ci	},
3408c2ecf20Sopenharmony_ci	{
3418c2ecf20Sopenharmony_ci		.actions_list = stm32_synapse_actions,
3428c2ecf20Sopenharmony_ci		.num_actions = ARRAY_SIZE(stm32_synapse_actions),
3438c2ecf20Sopenharmony_ci		.signal = &stm32_signals[1]
3448c2ecf20Sopenharmony_ci	}
3458c2ecf20Sopenharmony_ci};
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_cistatic struct counter_count stm32_counts = {
3488c2ecf20Sopenharmony_ci	.id = 0,
3498c2ecf20Sopenharmony_ci	.name = "Channel 1 Count",
3508c2ecf20Sopenharmony_ci	.functions_list = stm32_count_functions,
3518c2ecf20Sopenharmony_ci	.num_functions = ARRAY_SIZE(stm32_count_functions),
3528c2ecf20Sopenharmony_ci	.synapses = stm32_count_synapses,
3538c2ecf20Sopenharmony_ci	.num_synapses = ARRAY_SIZE(stm32_count_synapses),
3548c2ecf20Sopenharmony_ci	.ext = stm32_count_ext,
3558c2ecf20Sopenharmony_ci	.num_ext = ARRAY_SIZE(stm32_count_ext)
3568c2ecf20Sopenharmony_ci};
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_cistatic int stm32_timer_cnt_probe(struct platform_device *pdev)
3598c2ecf20Sopenharmony_ci{
3608c2ecf20Sopenharmony_ci	struct stm32_timers *ddata = dev_get_drvdata(pdev->dev.parent);
3618c2ecf20Sopenharmony_ci	struct device *dev = &pdev->dev;
3628c2ecf20Sopenharmony_ci	struct stm32_timer_cnt *priv;
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	if (IS_ERR_OR_NULL(ddata))
3658c2ecf20Sopenharmony_ci		return -EINVAL;
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
3688c2ecf20Sopenharmony_ci	if (!priv)
3698c2ecf20Sopenharmony_ci		return -ENOMEM;
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_ci	priv->regmap = ddata->regmap;
3728c2ecf20Sopenharmony_ci	priv->clk = ddata->clk;
3738c2ecf20Sopenharmony_ci	priv->max_arr = ddata->max_arr;
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ci	priv->counter.name = dev_name(dev);
3768c2ecf20Sopenharmony_ci	priv->counter.parent = dev;
3778c2ecf20Sopenharmony_ci	priv->counter.ops = &stm32_timer_cnt_ops;
3788c2ecf20Sopenharmony_ci	priv->counter.counts = &stm32_counts;
3798c2ecf20Sopenharmony_ci	priv->counter.num_counts = 1;
3808c2ecf20Sopenharmony_ci	priv->counter.signals = stm32_signals;
3818c2ecf20Sopenharmony_ci	priv->counter.num_signals = ARRAY_SIZE(stm32_signals);
3828c2ecf20Sopenharmony_ci	priv->counter.priv = priv;
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, priv);
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci	/* Register Counter device */
3878c2ecf20Sopenharmony_ci	return devm_counter_register(dev, &priv->counter);
3888c2ecf20Sopenharmony_ci}
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_cistatic int __maybe_unused stm32_timer_cnt_suspend(struct device *dev)
3918c2ecf20Sopenharmony_ci{
3928c2ecf20Sopenharmony_ci	struct stm32_timer_cnt *priv = dev_get_drvdata(dev);
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci	/* Only take care of enabled counter: don't disturb other MFD child */
3958c2ecf20Sopenharmony_ci	if (priv->enabled) {
3968c2ecf20Sopenharmony_ci		/* Backup registers that may get lost in low power mode */
3978c2ecf20Sopenharmony_ci		regmap_read(priv->regmap, TIM_SMCR, &priv->bak.smcr);
3988c2ecf20Sopenharmony_ci		regmap_read(priv->regmap, TIM_ARR, &priv->bak.arr);
3998c2ecf20Sopenharmony_ci		regmap_read(priv->regmap, TIM_CNT, &priv->bak.cnt);
4008c2ecf20Sopenharmony_ci		regmap_read(priv->regmap, TIM_CR1, &priv->bak.cr1);
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci		/* Disable the counter */
4038c2ecf20Sopenharmony_ci		regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0);
4048c2ecf20Sopenharmony_ci		clk_disable(priv->clk);
4058c2ecf20Sopenharmony_ci	}
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	return pinctrl_pm_select_sleep_state(dev);
4088c2ecf20Sopenharmony_ci}
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_cistatic int __maybe_unused stm32_timer_cnt_resume(struct device *dev)
4118c2ecf20Sopenharmony_ci{
4128c2ecf20Sopenharmony_ci	struct stm32_timer_cnt *priv = dev_get_drvdata(dev);
4138c2ecf20Sopenharmony_ci	int ret;
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci	ret = pinctrl_pm_select_default_state(dev);
4168c2ecf20Sopenharmony_ci	if (ret)
4178c2ecf20Sopenharmony_ci		return ret;
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	if (priv->enabled) {
4208c2ecf20Sopenharmony_ci		clk_enable(priv->clk);
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci		/* Restore registers that may have been lost */
4238c2ecf20Sopenharmony_ci		regmap_write(priv->regmap, TIM_SMCR, priv->bak.smcr);
4248c2ecf20Sopenharmony_ci		regmap_write(priv->regmap, TIM_ARR, priv->bak.arr);
4258c2ecf20Sopenharmony_ci		regmap_write(priv->regmap, TIM_CNT, priv->bak.cnt);
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci		/* Also re-enables the counter */
4288c2ecf20Sopenharmony_ci		regmap_write(priv->regmap, TIM_CR1, priv->bak.cr1);
4298c2ecf20Sopenharmony_ci	}
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci	return 0;
4328c2ecf20Sopenharmony_ci}
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(stm32_timer_cnt_pm_ops, stm32_timer_cnt_suspend,
4358c2ecf20Sopenharmony_ci			 stm32_timer_cnt_resume);
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_cistatic const struct of_device_id stm32_timer_cnt_of_match[] = {
4388c2ecf20Sopenharmony_ci	{ .compatible = "st,stm32-timer-counter", },
4398c2ecf20Sopenharmony_ci	{},
4408c2ecf20Sopenharmony_ci};
4418c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, stm32_timer_cnt_of_match);
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_cistatic struct platform_driver stm32_timer_cnt_driver = {
4448c2ecf20Sopenharmony_ci	.probe = stm32_timer_cnt_probe,
4458c2ecf20Sopenharmony_ci	.driver = {
4468c2ecf20Sopenharmony_ci		.name = "stm32-timer-counter",
4478c2ecf20Sopenharmony_ci		.of_match_table = stm32_timer_cnt_of_match,
4488c2ecf20Sopenharmony_ci		.pm = &stm32_timer_cnt_pm_ops,
4498c2ecf20Sopenharmony_ci	},
4508c2ecf20Sopenharmony_ci};
4518c2ecf20Sopenharmony_cimodule_platform_driver(stm32_timer_cnt_driver);
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ciMODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
4548c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:stm32-timer-counter");
4558c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("STMicroelectronics STM32 TIMER counter driver");
4568c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
457