summaryrefslogtreecommitdiffstats
path: root/drivers/counter/stm32-lptimer-cnt.c
diff options
context:
space:
mode:
authorWilliam Breathitt Gray <vilhelm.gray@gmail.com>2021-08-27 05:47:47 +0200
committerJonathan Cameron <Jonathan.Cameron@huawei.com>2021-10-17 11:52:58 +0200
commitaaec1a0f76ec25f46bbb17b81487c4b0e1c318c5 (patch)
treeb76c9daf90cf5f493fc865aca6dc8ed8a9798ea0 /drivers/counter/stm32-lptimer-cnt.c
parentcounter: stm32-timer-cnt: Provide defines for slave mode selection (diff)
downloadlinux-aaec1a0f76ec25f46bbb17b81487c4b0e1c318c5.tar.xz
linux-aaec1a0f76ec25f46bbb17b81487c4b0e1c318c5.zip
counter: Internalize sysfs interface code
This is a reimplementation of the Generic Counter driver interface. There are no modifications to the Counter subsystem userspace interface, so existing userspace applications should continue to run seamlessly. The purpose of this patch is to internalize the sysfs interface code among the various counter drivers into a shared module. Counter drivers pass and take data natively (i.e. u8, u64, etc.) and the shared counter module handles the translation between the sysfs interface and the device drivers. This guarantees a standard userspace interface for all counter drivers, and helps generalize the Generic Counter driver ABI in order to support the Generic Counter chrdev interface (introduced in a subsequent patch) without significant changes to the existing counter drivers. Note, Counter device registration is the same as before: drivers populate a struct counter_device with components and callbacks, then pass the structure to the devm_counter_register function. However, what's different now is how the Counter subsystem code handles this registration internally. Whereas before callbacks would interact directly with sysfs data, this interaction is now abstracted and instead callbacks interact with native C data types. The counter_comp structure forms the basis for Counter extensions. The counter-sysfs.c file contains the code to parse through the counter_device structure and register the requested components and extensions. Attributes are created and populated based on type, with respective translation functions to handle the mapping between sysfs and the counter driver callbacks. The translation performed for each attribute is straightforward: the attribute type and data is parsed from the counter_attribute structure, the respective counter driver read/write callback is called, and sysfs I/O is handled before or after the driver read/write function is called. Cc: Jarkko Nikula <jarkko.nikula@linux.intel.com> Cc: Patrick Havelange <patrick.havelange@essensium.com> Cc: Kamel Bouhara <kamel.bouhara@bootlin.com> Cc: Maxime Coquelin <mcoquelin.stm32@gmail.com> Cc: Alexandre Torgue <alexandre.torgue@st.com> Cc: Dan Carpenter <dan.carpenter@oracle.com> Acked-by: Syed Nayyar Waris <syednwaris@gmail.com> Reviewed-by: David Lechner <david@lechnology.com> Tested-by: David Lechner <david@lechnology.com> Signed-off-by: William Breathitt Gray <vilhelm.gray@gmail.com> Reviewed-by: Fabrice Gasnier <fabrice.gasnier@foss.st.com> # for stm32 Link: https://lore.kernel.org/r/c68b4a1ffb195c1a2f65e8dd5ad7b7c14e79c6ef.1630031207.git.vilhelm.gray@gmail.com Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Diffstat (limited to 'drivers/counter/stm32-lptimer-cnt.c')
-rw-r--r--drivers/counter/stm32-lptimer-cnt.c212
1 files changed, 100 insertions, 112 deletions
diff --git a/drivers/counter/stm32-lptimer-cnt.c b/drivers/counter/stm32-lptimer-cnt.c
index 7367f46c6f91..5168833b1fdf 100644
--- a/drivers/counter/stm32-lptimer-cnt.c
+++ b/drivers/counter/stm32-lptimer-cnt.c
@@ -17,6 +17,7 @@
#include <linux/module.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
+#include <linux/types.h>
struct stm32_lptim_cnt {
struct counter_device counter;
@@ -107,11 +108,7 @@ static int stm32_lptim_setup(struct stm32_lptim_cnt *priv, int enable)
return regmap_update_bits(priv->regmap, STM32_LPTIM_CFGR, mask, val);
}
-/**
- * enum stm32_lptim_cnt_function - enumerates LPTimer counter & encoder modes
- * @STM32_LPTIM_COUNTER_INCREASE: up count on IN1 rising, falling or both edges
- * @STM32_LPTIM_ENCODER_BOTH_EDGE: count on both edges (IN1 & IN2 quadrature)
- *
+/*
* In non-quadrature mode, device counts up on active edge.
* In quadrature mode, encoder counting scenarios are as follows:
* +---------+----------+--------------------+--------------------+
@@ -129,33 +126,20 @@ static int stm32_lptim_setup(struct stm32_lptim_cnt *priv, int enable)
* | edges | Low -> | Up | Down | Down | Up |
* +---------+----------+----------+---------+----------+---------+
*/
-enum stm32_lptim_cnt_function {
- STM32_LPTIM_COUNTER_INCREASE,
- STM32_LPTIM_ENCODER_BOTH_EDGE,
-};
-
static const enum counter_function stm32_lptim_cnt_functions[] = {
- [STM32_LPTIM_COUNTER_INCREASE] = COUNTER_FUNCTION_INCREASE,
- [STM32_LPTIM_ENCODER_BOTH_EDGE] = COUNTER_FUNCTION_QUADRATURE_X4,
-};
-
-enum stm32_lptim_synapse_action {
- STM32_LPTIM_SYNAPSE_ACTION_RISING_EDGE = STM32_LPTIM_CKPOL_RISING_EDGE,
- STM32_LPTIM_SYNAPSE_ACTION_FALLING_EDGE = STM32_LPTIM_CKPOL_FALLING_EDGE,
- STM32_LPTIM_SYNAPSE_ACTION_BOTH_EDGES = STM32_LPTIM_CKPOL_BOTH_EDGES,
- STM32_LPTIM_SYNAPSE_ACTION_NONE,
+ COUNTER_FUNCTION_INCREASE,
+ COUNTER_FUNCTION_QUADRATURE_X4,
};
static const enum counter_synapse_action stm32_lptim_cnt_synapse_actions[] = {
- /* Index must match with stm32_lptim_cnt_polarity[] (priv->polarity) */
- [STM32_LPTIM_SYNAPSE_ACTION_RISING_EDGE] = COUNTER_SYNAPSE_ACTION_RISING_EDGE,
- [STM32_LPTIM_SYNAPSE_ACTION_FALLING_EDGE] = COUNTER_SYNAPSE_ACTION_FALLING_EDGE,
- [STM32_LPTIM_SYNAPSE_ACTION_BOTH_EDGES] = COUNTER_SYNAPSE_ACTION_BOTH_EDGES,
- [STM32_LPTIM_SYNAPSE_ACTION_NONE] = COUNTER_SYNAPSE_ACTION_NONE,
+ COUNTER_SYNAPSE_ACTION_RISING_EDGE,
+ COUNTER_SYNAPSE_ACTION_FALLING_EDGE,
+ COUNTER_SYNAPSE_ACTION_BOTH_EDGES,
+ COUNTER_SYNAPSE_ACTION_NONE,
};
static int stm32_lptim_cnt_read(struct counter_device *counter,
- struct counter_count *count, unsigned long *val)
+ struct counter_count *count, u64 *val)
{
struct stm32_lptim_cnt *const priv = counter->priv;
u32 cnt;
@@ -170,28 +154,28 @@ static int stm32_lptim_cnt_read(struct counter_device *counter,
return 0;
}
-static int stm32_lptim_cnt_function_get(struct counter_device *counter,
- struct counter_count *count,
- size_t *function)
+static int stm32_lptim_cnt_function_read(struct counter_device *counter,
+ struct counter_count *count,
+ enum counter_function *function)
{
struct stm32_lptim_cnt *const priv = counter->priv;
if (!priv->quadrature_mode) {
- *function = STM32_LPTIM_COUNTER_INCREASE;
+ *function = COUNTER_FUNCTION_INCREASE;
return 0;
}
- if (priv->polarity == STM32_LPTIM_SYNAPSE_ACTION_BOTH_EDGES) {
- *function = STM32_LPTIM_ENCODER_BOTH_EDGE;
+ if (priv->polarity == STM32_LPTIM_CKPOL_BOTH_EDGES) {
+ *function = COUNTER_FUNCTION_QUADRATURE_X4;
return 0;
}
return -EINVAL;
}
-static int stm32_lptim_cnt_function_set(struct counter_device *counter,
- struct counter_count *count,
- size_t function)
+static int stm32_lptim_cnt_function_write(struct counter_device *counter,
+ struct counter_count *count,
+ enum counter_function function)
{
struct stm32_lptim_cnt *const priv = counter->priv;
@@ -199,12 +183,12 @@ static int stm32_lptim_cnt_function_set(struct counter_device *counter,
return -EBUSY;
switch (function) {
- case STM32_LPTIM_COUNTER_INCREASE:
+ case COUNTER_FUNCTION_INCREASE:
priv->quadrature_mode = 0;
return 0;
- case STM32_LPTIM_ENCODER_BOTH_EDGE:
+ case COUNTER_FUNCTION_QUADRATURE_X4:
priv->quadrature_mode = 1;
- priv->polarity = STM32_LPTIM_SYNAPSE_ACTION_BOTH_EDGES;
+ priv->polarity = STM32_LPTIM_CKPOL_BOTH_EDGES;
return 0;
default:
/* should never reach this path */
@@ -212,9 +196,9 @@ static int stm32_lptim_cnt_function_set(struct counter_device *counter,
}
}
-static ssize_t stm32_lptim_cnt_enable_read(struct counter_device *counter,
- struct counter_count *count,
- void *private, char *buf)
+static int stm32_lptim_cnt_enable_read(struct counter_device *counter,
+ struct counter_count *count,
+ u8 *enable)
{
struct stm32_lptim_cnt *const priv = counter->priv;
int ret;
@@ -223,22 +207,18 @@ static ssize_t stm32_lptim_cnt_enable_read(struct counter_device *counter,
if (ret < 0)
return ret;
- return scnprintf(buf, PAGE_SIZE, "%u\n", ret);
+ *enable = ret;
+
+ return 0;
}
-static ssize_t stm32_lptim_cnt_enable_write(struct counter_device *counter,
- struct counter_count *count,
- void *private,
- const char *buf, size_t len)
+static int stm32_lptim_cnt_enable_write(struct counter_device *counter,
+ struct counter_count *count,
+ u8 enable)
{
struct stm32_lptim_cnt *const priv = counter->priv;
- bool enable;
int ret;
- ret = kstrtobool(buf, &enable);
- if (ret)
- return ret;
-
/* Check nobody uses the timer, or already disabled/enabled */
ret = stm32_lptim_is_enabled(priv);
if ((ret < 0) || (!ret && !enable))
@@ -254,78 +234,81 @@ static ssize_t stm32_lptim_cnt_enable_write(struct counter_device *counter,
if (ret)
return ret;
- return len;
+ return 0;
}
-static ssize_t stm32_lptim_cnt_ceiling_read(struct counter_device *counter,
- struct counter_count *count,
- void *private, char *buf)
+static int stm32_lptim_cnt_ceiling_read(struct counter_device *counter,
+ struct counter_count *count,
+ u64 *ceiling)
{
struct stm32_lptim_cnt *const priv = counter->priv;
- return snprintf(buf, PAGE_SIZE, "%u\n", priv->ceiling);
+ *ceiling = priv->ceiling;
+
+ return 0;
}
-static ssize_t stm32_lptim_cnt_ceiling_write(struct counter_device *counter,
- struct counter_count *count,
- void *private,
- const char *buf, size_t len)
+static int stm32_lptim_cnt_ceiling_write(struct counter_device *counter,
+ struct counter_count *count,
+ u64 ceiling)
{
struct stm32_lptim_cnt *const priv = counter->priv;
- unsigned int ceiling;
- int ret;
if (stm32_lptim_is_enabled(priv))
return -EBUSY;
- ret = kstrtouint(buf, 0, &ceiling);
- if (ret)
- return ret;
-
if (ceiling > STM32_LPTIM_MAX_ARR)
return -ERANGE;
priv->ceiling = ceiling;
- return len;
+ return 0;
}
-static const struct counter_count_ext stm32_lptim_cnt_ext[] = {
- {
- .name = "enable",
- .read = stm32_lptim_cnt_enable_read,
- .write = stm32_lptim_cnt_enable_write
- },
- {
- .name = "ceiling",
- .read = stm32_lptim_cnt_ceiling_read,
- .write = stm32_lptim_cnt_ceiling_write
- },
+static struct counter_comp stm32_lptim_cnt_ext[] = {
+ COUNTER_COMP_ENABLE(stm32_lptim_cnt_enable_read,
+ stm32_lptim_cnt_enable_write),
+ COUNTER_COMP_CEILING(stm32_lptim_cnt_ceiling_read,
+ stm32_lptim_cnt_ceiling_write),
};
-static int stm32_lptim_cnt_action_get(struct counter_device *counter,
- struct counter_count *count,
- struct counter_synapse *synapse,
- size_t *action)
+static int stm32_lptim_cnt_action_read(struct counter_device *counter,
+ struct counter_count *count,
+ struct counter_synapse *synapse,
+ enum counter_synapse_action *action)
{
struct stm32_lptim_cnt *const priv = counter->priv;
- size_t function;
+ enum counter_function function;
int err;
- err = stm32_lptim_cnt_function_get(counter, count, &function);
+ err = stm32_lptim_cnt_function_read(counter, count, &function);
if (err)
return err;
switch (function) {
- case STM32_LPTIM_COUNTER_INCREASE:
+ case COUNTER_FUNCTION_INCREASE:
/* LP Timer acts as up-counter on input 1 */
- if (synapse->signal->id == count->synapses[0].signal->id)
- *action = priv->polarity;
- else
- *action = STM32_LPTIM_SYNAPSE_ACTION_NONE;
- return 0;
- case STM32_LPTIM_ENCODER_BOTH_EDGE:
- *action = priv->polarity;
+ if (synapse->signal->id != count->synapses[0].signal->id) {
+ *action = COUNTER_SYNAPSE_ACTION_NONE;
+ return 0;
+ }
+
+ switch (priv->polarity) {
+ case STM32_LPTIM_CKPOL_RISING_EDGE:
+ *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
+ return 0;
+ case STM32_LPTIM_CKPOL_FALLING_EDGE:
+ *action = COUNTER_SYNAPSE_ACTION_FALLING_EDGE;
+ return 0;
+ case STM32_LPTIM_CKPOL_BOTH_EDGES:
+ *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
+ return 0;
+ default:
+ /* should never reach this path */
+ return -EINVAL;
+ }
+ case COUNTER_FUNCTION_QUADRATURE_X4:
+ *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
return 0;
default:
/* should never reach this path */
@@ -333,43 +316,48 @@ static int stm32_lptim_cnt_action_get(struct counter_device *counter,
}
}
-static int stm32_lptim_cnt_action_set(struct counter_device *counter,
- struct counter_count *count,
- struct counter_synapse *synapse,
- size_t action)
+static int stm32_lptim_cnt_action_write(struct counter_device *counter,
+ struct counter_count *count,
+ struct counter_synapse *synapse,
+ enum counter_synapse_action action)
{
struct stm32_lptim_cnt *const priv = counter->priv;
- size_t function;
+ enum counter_function function;
int err;
if (stm32_lptim_is_enabled(priv))
return -EBUSY;
- err = stm32_lptim_cnt_function_get(counter, count, &function);
+ err = stm32_lptim_cnt_function_read(counter, count, &function);
if (err)
return err;
/* only set polarity when in counter mode (on input 1) */
- if (function == STM32_LPTIM_COUNTER_INCREASE
- && synapse->signal->id == count->synapses[0].signal->id) {
- switch (action) {
- case STM32_LPTIM_SYNAPSE_ACTION_RISING_EDGE:
- case STM32_LPTIM_SYNAPSE_ACTION_FALLING_EDGE:
- case STM32_LPTIM_SYNAPSE_ACTION_BOTH_EDGES:
- priv->polarity = action;
- return 0;
- }
- }
+ if (function != COUNTER_FUNCTION_INCREASE
+ || synapse->signal->id != count->synapses[0].signal->id)
+ return -EINVAL;
- return -EINVAL;
+ switch (action) {
+ case COUNTER_SYNAPSE_ACTION_RISING_EDGE:
+ priv->polarity = STM32_LPTIM_CKPOL_RISING_EDGE;
+ return 0;
+ case COUNTER_SYNAPSE_ACTION_FALLING_EDGE:
+ priv->polarity = STM32_LPTIM_CKPOL_FALLING_EDGE;
+ return 0;
+ case COUNTER_SYNAPSE_ACTION_BOTH_EDGES:
+ priv->polarity = STM32_LPTIM_CKPOL_BOTH_EDGES;
+ return 0;
+ default:
+ return -EINVAL;
+ }
}
static const struct counter_ops stm32_lptim_cnt_ops = {
.count_read = stm32_lptim_cnt_read,
- .function_get = stm32_lptim_cnt_function_get,
- .function_set = stm32_lptim_cnt_function_set,
- .action_get = stm32_lptim_cnt_action_get,
- .action_set = stm32_lptim_cnt_action_set,
+ .function_read = stm32_lptim_cnt_function_read,
+ .function_write = stm32_lptim_cnt_function_write,
+ .action_read = stm32_lptim_cnt_action_read,
+ .action_write = stm32_lptim_cnt_action_write,
};
static struct counter_signal stm32_lptim_cnt_signals[] = {