* [PATCH v4 3/4] mfd: Add RZ/G2L MTU3 counter driver
[not found] <20221010145222.1047748-1-biju.das.jz@bp.renesas.com>
@ 2022-10-10 14:52 ` Biju Das
2022-10-17 16:40 ` William Breathitt Gray
2022-10-25 13:50 ` Geert Uytterhoeven
0 siblings, 2 replies; 6+ messages in thread
From: Biju Das @ 2022-10-10 14:52 UTC (permalink / raw)
To: William Breathitt Gray, Philipp Zabel
Cc: Biju Das, Lee Jones, linux-iio, Geert Uytterhoeven,
Chris Paterson, Biju Das, Prabhakar Mahadev Lad,
linux-renesas-soc
Add RZ/G2L MTU3 counter driver. This IP supports the following
phase counting modes on MTU1 and MTU2 channels
1) 16-bit phase counting modes on MTU1 and MTU2 channels.
2) 32-bit phase counting mode by cascading MTU1 and MTU2.
This patch adds 3 counters by creating 3 logical channels
counter0: 16-bit phase counter on MTU1 channel
counter1: 16-bit phase counter on MTU2 channel
counter2: 32-bit phase counter by cascading MTU1 and MTU2
channels.
Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
v3->v4:
* There is no resource associated with "rz-mtu3-counter" compatible
and moved the code to mfd subsystem as it binds against "rz-mtu".
* Removed struct platform_driver rz_mtu3_cnt_driver.
* Updated commit description
* Updated Kconfig description
* Added macros RZ_MTU3_16_BIT_MTU{1,2}_CH for MTU1 and MTU2 channels
* Added RZ_MTU3_GET_HW_CH macro for getting channel ID.
* replaced priv->ch[id]->priv->ch[0] in rz_mtu3_count_read()
* Cached counter max values
* replaced cnt->tsr in rz_mtu3_count_direction_read()
* Added comments for RZ_MTU3_TCR_CCLR_NONE
* Replaced if with switch in rz_mtu3_initialize_counter() and
rz_mtu3_count_ceiling_write()
* Added locks in initialize, terminate and enable_read to prevent races.
* Updated rz_mtu3_action_read to take care of MTU2 signals.
* Added separate distinct array for each group of Synapse.
* Moved pm handling to parent.
v1->v3:
* Modelled as a counter device supporting 3 counters(2 16-bit and
32-bit)
* Add kernel-doc comments to document struct rz_mtu3_cnt
* Removed mmio variable from struct rz_mtu3_cnt
* Removed cnt local variable from rz_mtu3_count_read()
* Replaced -EINVAL->-ERANGE for out of range error conditions.
* Removed explicit cast from write functions.
* Removed local variable val from rz_mtu3_count_ceiling_read()
* Added lock for RMW for counter/ceiling updates.
* Added different synapses for counter0 and counter{1,2}
* Used ARRAY for assigning num_counts.
* Added PM runtime for managing clocks.
* Add MODULE_IMPORT_NS(COUNTER) to import the COUNTER namespace.
---
drivers/mfd/Kconfig | 8 +
drivers/mfd/Makefile | 1 +
drivers/mfd/rz-mtu3-cnt.c | 554 ++++++++++++++++++++++++++++++++++++++
3 files changed, 563 insertions(+)
create mode 100644 drivers/mfd/rz-mtu3-cnt.c
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 7329971a3bdf..fa88056224c9 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1986,6 +1986,14 @@ config MFD_RZ_MTU3
To compile this driver as a module, choose M here: the
module will be called rz-mtu3.
+config MFD_RZ_MTU3_CNT
+ tristate "RZ/G2L MTU3 counter driver"
+ depends on MFD_RZ_MTU3 || COMPILE_TEST
+ help
+ Enable support for MTU3 counter driver found on Renesas RZ/G2L alike
+ SoCs. This IP supports both 16-bit and 32-bit phase counting mode
+ support.
+
config MFD_STM32_LPTIMER
tristate "Support for STM32 Low-Power Timer"
depends on (ARCH_STM32 && OF) || COMPILE_TEST
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index cd492903411c..9d0d1fd22f99 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -252,6 +252,7 @@ obj-$(CONFIG_MFD_STPMIC1) += stpmic1.o
obj-$(CONFIG_MFD_SUN4I_GPADC) += sun4i-gpadc.o
rz-mtu3-objs := rz-mtu3-core.o
+rz-mtu3-$(CONFIG_MFD_RZ_MTU3_CNT) += rz-mtu3-cnt.o
obj-$(CONFIG_MFD_RZ_MTU3) += rz-mtu3.o
obj-$(CONFIG_MFD_STM32_LPTIMER) += stm32-lptimer.o
obj-$(CONFIG_MFD_STM32_TIMERS) += stm32-timers.o
diff --git a/drivers/mfd/rz-mtu3-cnt.c b/drivers/mfd/rz-mtu3-cnt.c
new file mode 100644
index 000000000000..e4aef25be462
--- /dev/null
+++ b/drivers/mfd/rz-mtu3-cnt.c
@@ -0,0 +1,554 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas RZ/G2L MTU3a Counter driver
+ *
+ * Copyright (C) 2022 Renesas Electronics Corporation
+ */
+#include <linux/counter.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/types.h>
+
+#include "rz-mtu3.h"
+
+#define RZ_MTU3_TSR_TCFD BIT(7)
+#define RZ_MTU3_MAX_HW_CNTR_CHANNELS (2)
+
+#define RZ_MTU3_TMDR1_PH_CNT_MODE_1 (4)
+#define RZ_MTU3_TMDR1_PH_CNT_MODE_2 (5)
+#define RZ_MTU3_TMDR1_PH_CNT_MODE_3 (6)
+#define RZ_MTU3_TMDR1_PH_CNT_MODE_4 (7)
+#define RZ_MTU3_TMDR1_PH_CNT_MODE_5 (9)
+#define RZ_MTU3_TMDR1_PH_CNT_MODE_MASK (0xf)
+
+#define RZ_MTU3_TCR_CCLR GENMASK(7, 5)
+#define RZ_MTU3_TCR_CCLR_NONE FIELD_PREP(RZ_MTU3_TCR_CCLR, 0)
+
+#define RZ_MTU3_TMDR3_LWA BIT(0)
+#define RZ_MTU3_16_BIT_MTU1_CH (0)
+#define RZ_MTU3_16_BIT_MTU2_CH (1)
+#define RZ_MTU3_32_BIT_CH (2)
+
+#define RZ_MTU3_TIOR_IC_BOTH (10)
+
+#define RZ_MTU3_GET_HW_CH(id) (((id) == RZ_MTU3_32_BIT_CH) ? 0 : (id))
+
+/**
+ * struct rz_mtu3_cnt - MTU3 counter private data
+ *
+ * @lock: Lock to prevent concurrent access for ceiling and count
+ * @mtu_16bit_max: Cache for 16-bit counters
+ * @mtu_32bit_max: Cache for 32-bit counters
+ * @rz_mtu3_channel: HW channels for the counters
+ */
+struct rz_mtu3_cnt {
+ struct mutex lock;
+ u16 mtu_16bit_max[RZ_MTU3_MAX_HW_CNTR_CHANNELS];
+ u32 mtu_32bit_max;
+ struct rz_mtu3_channel *ch[RZ_MTU3_MAX_HW_CNTR_CHANNELS];
+};
+
+static const enum counter_function rz_mtu3_count_functions[] = {
+ COUNTER_FUNCTION_QUADRATURE_X4,
+ COUNTER_FUNCTION_PULSE_DIRECTION,
+ COUNTER_FUNCTION_QUADRATURE_X2_B,
+};
+
+static int rz_mtu3_count_read(struct counter_device *counter,
+ struct counter_count *count, u64 *val)
+{
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+
+ if (count->id == RZ_MTU3_32_BIT_CH)
+ *val = rz_mtu3_32bit_ch_read(priv->ch[0], RZ_MTU3_TCNTLW);
+ else
+ *val = rz_mtu3_16bit_ch_read(priv->ch[count->id], RZ_MTU3_TCNT);
+
+ return 0;
+}
+
+static int rz_mtu3_count_write(struct counter_device *counter,
+ struct counter_count *count, const u64 val)
+{
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+ const size_t ch_id = RZ_MTU3_GET_HW_CH(count->id);
+ u32 ceiling;
+
+ mutex_lock(&priv->lock);
+ if (count->id == RZ_MTU3_32_BIT_CH)
+ ceiling = priv->mtu_32bit_max;
+ else
+ ceiling = priv->mtu_16bit_max[ch_id];
+
+ if (val > ceiling) {
+ mutex_unlock(&priv->lock);
+ return -ERANGE;
+ }
+
+ if (count->id == RZ_MTU3_32_BIT_CH)
+ rz_mtu3_32bit_ch_write(priv->ch[0], RZ_MTU3_TCNTLW, val);
+ else
+ rz_mtu3_16bit_ch_write(priv->ch[ch_id], RZ_MTU3_TCNT, val);
+
+ mutex_unlock(&priv->lock);
+
+ return 0;
+}
+
+static int rz_mtu3_count_function_read(struct counter_device *counter,
+ struct counter_count *count,
+ enum counter_function *function)
+{
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+ const size_t ch_id = RZ_MTU3_GET_HW_CH(count->id);
+ u8 val;
+
+ val = rz_mtu3_8bit_ch_read(priv->ch[ch_id], RZ_MTU3_TMDR1);
+
+ switch (val & RZ_MTU3_TMDR1_PH_CNT_MODE_MASK) {
+ case RZ_MTU3_TMDR1_PH_CNT_MODE_1:
+ *function = COUNTER_FUNCTION_QUADRATURE_X4;
+ break;
+ case RZ_MTU3_TMDR1_PH_CNT_MODE_2:
+ *function = COUNTER_FUNCTION_PULSE_DIRECTION;
+ break;
+ case RZ_MTU3_TMDR1_PH_CNT_MODE_4:
+ *function = COUNTER_FUNCTION_QUADRATURE_X2_B;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int rz_mtu3_count_function_write(struct counter_device *counter,
+ struct counter_count *count,
+ enum counter_function function)
+{
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+ const size_t ch_id = RZ_MTU3_GET_HW_CH(count->id);
+ u8 mode;
+
+ switch (function) {
+ case COUNTER_FUNCTION_QUADRATURE_X4:
+ mode = RZ_MTU3_TMDR1_PH_CNT_MODE_1;
+ break;
+ case COUNTER_FUNCTION_PULSE_DIRECTION:
+ mode = RZ_MTU3_TMDR1_PH_CNT_MODE_2;
+ break;
+ case COUNTER_FUNCTION_QUADRATURE_X2_B:
+ mode = RZ_MTU3_TMDR1_PH_CNT_MODE_4;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ rz_mtu3_8bit_ch_write(priv->ch[ch_id], RZ_MTU3_TMDR1, mode);
+
+ return 0;
+}
+
+static int rz_mtu3_count_direction_read(struct counter_device *counter,
+ struct counter_count *count,
+ enum counter_count_direction *direction)
+{
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+ const size_t ch_id = RZ_MTU3_GET_HW_CH(count->id);
+ u8 tsr;
+
+ tsr = rz_mtu3_8bit_ch_read(priv->ch[ch_id], RZ_MTU3_TSR);
+
+ if (tsr & RZ_MTU3_TSR_TCFD)
+ *direction = COUNTER_COUNT_DIRECTION_FORWARD;
+ else
+ *direction = COUNTER_COUNT_DIRECTION_BACKWARD;
+
+ return 0;
+}
+
+static int rz_mtu3_count_ceiling_read(struct counter_device *counter,
+ struct counter_count *count,
+ u64 *ceiling)
+{
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+ const size_t ch_id = RZ_MTU3_GET_HW_CH(count->id);
+
+ if (count->id == RZ_MTU3_32_BIT_CH)
+ *ceiling = priv->mtu_32bit_max;
+ else
+ *ceiling = priv->mtu_16bit_max[ch_id];
+
+ return 0;
+}
+
+static int rz_mtu3_count_ceiling_write(struct counter_device *counter,
+ struct counter_count *count,
+ u64 ceiling)
+{
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+ const size_t ch_id = RZ_MTU3_GET_HW_CH(count->id);
+
+ switch (count->id) {
+ case RZ_MTU3_16_BIT_MTU1_CH:
+ case RZ_MTU3_16_BIT_MTU2_CH:
+ if (ceiling > U16_MAX)
+ return -ERANGE;
+ priv->mtu_16bit_max[ch_id] = ceiling;
+ break;
+ case RZ_MTU3_32_BIT_CH:
+ if (ceiling > U32_MAX)
+ return -ERANGE;
+ priv->mtu_32bit_max = ceiling;
+ break;
+ }
+
+ mutex_lock(&priv->lock);
+ if (ceiling == 0) {
+ /* Disable counter clear source */
+ rz_mtu3_8bit_ch_write(priv->ch[ch_id], RZ_MTU3_TCR,
+ RZ_MTU3_TCR_CCLR_NONE);
+ } else {
+ if (count->id == RZ_MTU3_32_BIT_CH)
+ rz_mtu3_32bit_ch_write(priv->ch[ch_id], RZ_MTU3_TGRALW,
+ ceiling);
+ else
+ rz_mtu3_16bit_ch_write(priv->ch[ch_id], RZ_MTU3_TGRA,
+ ceiling);
+
+ rz_mtu3_8bit_ch_write(priv->ch[ch_id], RZ_MTU3_TCR,
+ RZ_MTU3_TCR_CCLR_TGRA);
+ }
+ mutex_unlock(&priv->lock);
+
+ return 0;
+}
+
+static void rz_mtu3_32bit_cnt_setting(struct counter_device *counter, int id)
+{
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+
+ /*
+ * 32-bit phase counting need MTU1 and MTU2 to create 32-bit cascade
+ * counter.
+ */
+ priv->ch[0]->function = RZ_MTU3_32BIT_PHASE_COUNTING;
+ priv->ch[1]->function = RZ_MTU3_32BIT_PHASE_COUNTING;
+
+ rz_mtu3_shared_reg_write(priv->ch[0], RZ_MTU3_TMDR3, RZ_MTU3_TMDR3_LWA);
+
+ /* Phase counting mode 1 is used as default in initialization. */
+ rz_mtu3_8bit_ch_write(priv->ch[0], RZ_MTU3_TMDR1,
+ RZ_MTU3_TMDR1_PH_CNT_MODE_1);
+
+ rz_mtu3_8bit_ch_write(priv->ch[0], RZ_MTU3_TCR, RZ_MTU3_TCR_CCLR_TGRA);
+ rz_mtu3_8bit_ch_write(priv->ch[0], RZ_MTU3_TIOR, RZ_MTU3_TIOR_IC_BOTH);
+
+ rz_mtu3_enable(priv->ch[0]);
+ rz_mtu3_enable(priv->ch[1]);
+}
+
+static void rz_mtu3_16bit_cnt_setting(struct counter_device *counter, int id)
+{
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+
+ priv->ch[id]->function = RZ_MTU3_16BIT_PHASE_COUNTING;
+
+ rz_mtu3_shared_reg_write(priv->ch[0], RZ_MTU3_TMDR3, 0);
+ /* Phase counting mode 1 is used as default in initialization. */
+ rz_mtu3_8bit_ch_write(priv->ch[id], RZ_MTU3_TMDR1,
+ RZ_MTU3_TMDR1_PH_CNT_MODE_1);
+
+ rz_mtu3_8bit_ch_write(priv->ch[id], RZ_MTU3_TCR, RZ_MTU3_TCR_CCLR_TGRA);
+ rz_mtu3_enable(priv->ch[id]);
+}
+
+static int rz_mtu3_initialize_counter(struct counter_device *counter, int id)
+{
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+
+ mutex_lock(&priv->lock);
+ switch (id) {
+ case RZ_MTU3_16_BIT_MTU1_CH:
+ case RZ_MTU3_16_BIT_MTU2_CH:
+ if (priv->ch[id]->function != RZ_MTU3_NORMAL) {
+ mutex_unlock(&priv->lock);
+ return -EBUSY;
+ }
+
+ rz_mtu3_16bit_cnt_setting(counter, id);
+ break;
+ case RZ_MTU3_32_BIT_CH:
+ if (priv->ch[0]->function != RZ_MTU3_NORMAL ||
+ priv->ch[1]->function != RZ_MTU3_NORMAL) {
+ mutex_unlock(&priv->lock);
+ return -EBUSY;
+ }
+ rz_mtu3_32bit_cnt_setting(counter, id);
+ break;
+ }
+ mutex_unlock(&priv->lock);
+
+ return 0;
+}
+
+static void rz_mtu3_terminate_counter(struct counter_device *counter, int id)
+{
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+
+ mutex_lock(&priv->lock);
+ if (id == RZ_MTU3_32_BIT_CH) {
+ priv->ch[0]->function = RZ_MTU3_NORMAL;
+ priv->ch[1]->function = RZ_MTU3_NORMAL;
+ rz_mtu3_shared_reg_write(priv->ch[0], RZ_MTU3_TMDR3, 0);
+ rz_mtu3_disable(priv->ch[1]);
+ rz_mtu3_disable(priv->ch[0]);
+ } else {
+ priv->ch[id]->function = RZ_MTU3_NORMAL;
+ rz_mtu3_disable(priv->ch[id]);
+ }
+ mutex_unlock(&priv->lock);
+}
+
+static int rz_mtu3_count_enable_read(struct counter_device *counter,
+ struct counter_count *count, u8 *enable)
+{
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+
+ if (count->id == RZ_MTU3_32_BIT_CH) {
+ mutex_lock(&priv->lock);
+ *enable = rz_mtu3_is_enabled(priv->ch[0]) &&
+ rz_mtu3_is_enabled(priv->ch[1]);
+ mutex_unlock(&priv->lock);
+ } else {
+ *enable = rz_mtu3_is_enabled(priv->ch[count->id]);
+ }
+
+ return 0;
+}
+
+static int rz_mtu3_count_enable_write(struct counter_device *counter,
+ struct counter_count *count, u8 enable)
+{
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+ const size_t ch_id = RZ_MTU3_GET_HW_CH(count->id);
+ struct rz_mtu3_channel *ch = priv->ch[ch_id];
+ int ret = 0;
+
+ if (enable) {
+ pm_runtime_get_sync(ch->dev);
+ ret = rz_mtu3_initialize_counter(counter, count->id);
+ } else {
+ rz_mtu3_terminate_counter(counter, count->id);
+ pm_runtime_put(ch->dev);
+ }
+
+ return ret;
+}
+
+static struct counter_comp rz_mtu3_count_ext[] = {
+ COUNTER_COMP_DIRECTION(rz_mtu3_count_direction_read),
+ COUNTER_COMP_ENABLE(rz_mtu3_count_enable_read,
+ rz_mtu3_count_enable_write),
+ COUNTER_COMP_CEILING(rz_mtu3_count_ceiling_read,
+ rz_mtu3_count_ceiling_write),
+};
+
+static const enum counter_synapse_action rz_mtu3_synapse_actions[] = {
+ COUNTER_SYNAPSE_ACTION_BOTH_EDGES,
+ COUNTER_SYNAPSE_ACTION_RISING_EDGE,
+ COUNTER_SYNAPSE_ACTION_NONE,
+};
+
+static int rz_mtu3_action_read(struct counter_device *counter,
+ struct counter_count *count,
+ struct counter_synapse *synapse,
+ enum counter_synapse_action *action)
+{
+ const size_t signal_a_id = count->synapses[0].signal->id;
+ const size_t signal_b_id = count->synapses[1].signal->id;
+ size_t signal_c_id;
+ size_t signal_d_id;
+ enum counter_function function;
+ int err;
+
+ if (count->id != RZ_MTU3_16_BIT_MTU1_CH) {
+ signal_c_id = count->synapses[2].signal->id;
+ signal_d_id = count->synapses[3].signal->id;
+ }
+
+ err = rz_mtu3_count_function_read(counter, count, &function);
+ if (err)
+ return err;
+
+ /* Default action mode */
+ *action = COUNTER_SYNAPSE_ACTION_NONE;
+
+ switch (function) {
+ case COUNTER_FUNCTION_PULSE_DIRECTION:
+ /*
+ * Rising edges on signal A updates the respective count.
+ * The input level of signal B determines direction.
+ */
+ if (synapse->signal->id == signal_a_id ||
+ synapse->signal->id == signal_c_id)
+ *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
+ break;
+ case COUNTER_FUNCTION_QUADRATURE_X2_B:
+ /*
+ * Any state transition on quadrature pair signal B updates
+ * the respective count.
+ */
+ if (synapse->signal->id == signal_b_id ||
+ synapse->signal->id == signal_d_id)
+ *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
+ break;
+ case COUNTER_FUNCTION_QUADRATURE_X4:
+ /* counts up/down on both edges of A and B signal*/
+ *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct counter_ops rz_mtu3_cnt_ops = {
+ .count_read = rz_mtu3_count_read,
+ .count_write = rz_mtu3_count_write,
+ .function_read = rz_mtu3_count_function_read,
+ .function_write = rz_mtu3_count_function_write,
+ .action_read = rz_mtu3_action_read,
+};
+
+#define RZ_MTU3_PHASE_SIGNAL(_id, _name) { \
+ .id = (_id), \
+ .name = (_name), \
+}
+
+static struct counter_signal rz_mtu3_signals[] = {
+ RZ_MTU3_PHASE_SIGNAL(0, "MTU1 MTCLKA"),
+ RZ_MTU3_PHASE_SIGNAL(1, "MTU1 MTCLKB"),
+ RZ_MTU3_PHASE_SIGNAL(2, "MTU2 MTCLKC"),
+ RZ_MTU3_PHASE_SIGNAL(3, "MTU2 MTCLKD"),
+};
+
+static struct counter_synapse rz_mtu3_mtu1_count_synapses[] = {
+ {
+ .actions_list = rz_mtu3_synapse_actions,
+ .num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
+ .signal = rz_mtu3_signals,
+ },
+ {
+ .actions_list = rz_mtu3_synapse_actions,
+ .num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
+ .signal = rz_mtu3_signals + 1,
+ }
+};
+
+static struct counter_synapse rz_mtu3_mtu2_count_synapses[] = {
+ {
+ .actions_list = rz_mtu3_synapse_actions,
+ .num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
+ .signal = rz_mtu3_signals,
+ },
+ {
+ .actions_list = rz_mtu3_synapse_actions,
+ .num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
+ .signal = rz_mtu3_signals + 1,
+ },
+ {
+ .actions_list = rz_mtu3_synapse_actions,
+ .num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
+ .signal = rz_mtu3_signals + 2,
+ },
+ {
+ .actions_list = rz_mtu3_synapse_actions,
+ .num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
+ .signal = rz_mtu3_signals + 3,
+ }
+};
+
+static struct counter_count rz_mtu3_counts[] = {
+ {
+ .id = RZ_MTU3_16_BIT_MTU1_CH,
+ .name = "Channel 1 phase counter",
+ .functions_list = rz_mtu3_count_functions,
+ .num_functions = ARRAY_SIZE(rz_mtu3_count_functions),
+ .synapses = rz_mtu3_mtu1_count_synapses,
+ .num_synapses = ARRAY_SIZE(rz_mtu3_mtu1_count_synapses),
+ .ext = rz_mtu3_count_ext,
+ .num_ext = ARRAY_SIZE(rz_mtu3_count_ext),
+ },
+ {
+ .id = RZ_MTU3_16_BIT_MTU2_CH,
+ .name = "Channel 2 phase counter",
+ .functions_list = rz_mtu3_count_functions,
+ .num_functions = ARRAY_SIZE(rz_mtu3_count_functions),
+ .synapses = rz_mtu3_mtu2_count_synapses,
+ .num_synapses = ARRAY_SIZE(rz_mtu3_mtu2_count_synapses),
+ .ext = rz_mtu3_count_ext,
+ .num_ext = ARRAY_SIZE(rz_mtu3_count_ext),
+ },
+ {
+ .id = RZ_MTU3_32_BIT_CH,
+ .name = "Channel 3 Cascaded phase counter",
+ .functions_list = rz_mtu3_count_functions,
+ .num_functions = ARRAY_SIZE(rz_mtu3_count_functions),
+ .synapses = rz_mtu3_mtu2_count_synapses,
+ .num_synapses = ARRAY_SIZE(rz_mtu3_mtu2_count_synapses),
+ .ext = rz_mtu3_count_ext,
+ .num_ext = ARRAY_SIZE(rz_mtu3_count_ext),
+ }
+};
+
+int rz_mtu3_cnt_probe(struct platform_device *pdev)
+{
+ struct rz_mtu3 *ddata = dev_get_drvdata(&pdev->dev);
+ struct device *dev = &pdev->dev;
+ struct counter_device *counter;
+ struct rz_mtu3_cnt *priv;
+ unsigned int i;
+ int ret;
+
+ counter = devm_counter_alloc(dev, sizeof(*priv));
+ if (!counter)
+ return -ENOMEM;
+
+ priv = counter_priv(counter);
+ ddata->cnt_priv = priv;
+
+ for (i = 0; i < RZ_MTU3_MAX_HW_CNTR_CHANNELS; i++) {
+ priv->ch[i] = &ddata->channels[RZ_MTU1 + i];
+ priv->ch[i]->dev = dev;
+ priv->mtu_16bit_max[i] = U16_MAX;
+ }
+
+ priv->mtu_32bit_max = U32_MAX;
+
+ mutex_init(&priv->lock);
+
+ counter->name = dev_name(dev);
+ counter->parent = dev;
+ counter->ops = &rz_mtu3_cnt_ops;
+ counter->counts = rz_mtu3_counts;
+ counter->num_counts = ARRAY_SIZE(rz_mtu3_counts);
+ counter->signals = rz_mtu3_signals;
+ counter->num_signals = ARRAY_SIZE(rz_mtu3_signals);
+
+ /* Register Counter device */
+ ret = devm_counter_add(dev, counter);
+ if (ret < 0)
+ dev_err_probe(dev, ret, "Failed to add counter\n");
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(rz_mtu3_cnt_probe);
+
+MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
+MODULE_DESCRIPTION("Renesas RZ/G2L MTU3a counter driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(COUNTER);
--
2.25.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v4 3/4] mfd: Add RZ/G2L MTU3 counter driver
2022-10-10 14:52 ` [PATCH v4 3/4] mfd: Add RZ/G2L MTU3 counter driver Biju Das
@ 2022-10-17 16:40 ` William Breathitt Gray
2022-10-17 19:58 ` Biju Das
2022-10-25 13:50 ` Geert Uytterhoeven
1 sibling, 1 reply; 6+ messages in thread
From: William Breathitt Gray @ 2022-10-17 16:40 UTC (permalink / raw)
To: Biju Das
Cc: Philipp Zabel, Lee Jones, linux-iio, Geert Uytterhoeven,
Chris Paterson, Biju Das, Prabhakar Mahadev Lad,
linux-renesas-soc
[-- Attachment #1: Type: text/plain, Size: 7624 bytes --]
On Mon, Oct 10, 2022 at 03:52:21PM +0100, Biju Das wrote:
> Add RZ/G2L MTU3 counter driver. This IP supports the following
> phase counting modes on MTU1 and MTU2 channels
>
> 1) 16-bit phase counting modes on MTU1 and MTU2 channels.
> 2) 32-bit phase counting mode by cascading MTU1 and MTU2.
>
> This patch adds 3 counters by creating 3 logical channels
> counter0: 16-bit phase counter on MTU1 channel
> counter1: 16-bit phase counter on MTU2 channel
> counter2: 32-bit phase counter by cascading MTU1 and MTU2
> channels.
>
> Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Hello Biju,
We discussed some changes already for v5, but I have some additional
comments and questions below.
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 7329971a3bdf..fa88056224c9 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -1986,6 +1986,14 @@ config MFD_RZ_MTU3
> To compile this driver as a module, choose M here: the
> module will be called rz-mtu3.
>
> +config MFD_RZ_MTU3_CNT
> + tristate "RZ/G2L MTU3 counter driver"
This is a nitpick, but include the manufacturer name in the tristate
string for the sake of clarity: "Renesas RZ/G2L MTU3 counter driver".
> + depends on MFD_RZ_MTU3 || COMPILE_TEST
I noticed you include <linux/of.h> in the rz-mtu3-cnt.c file; do you
need to depend on OF here in the Kconfig as well?
> +static int rz_mtu3_count_read(struct counter_device *counter,
> + struct counter_count *count, u64 *val)
> +{
> + struct rz_mtu3_cnt *const priv = counter_priv(counter);
> +
> + if (count->id == RZ_MTU3_32_BIT_CH)
> + *val = rz_mtu3_32bit_ch_read(priv->ch[0], RZ_MTU3_TCNTLW);
> + else
> + *val = rz_mtu3_16bit_ch_read(priv->ch[count->id], RZ_MTU3_TCNT);
After considering this again, I think it'll be better to match the
structure of the rest of the functions in this driver for consistency.
Rather than hardcoding priv->ch[0], determine the ch_id first and pass
that instead::
const size_t ch_id = RZ_MTU3_GET_HW_CH(count->id);
if (count->id == RZ_MTU3_32_BIT_CH)
*val = rz_mtu3_32bit_ch_read(priv->ch[ch_id], RZ_MTU3_TCNTLW);
else
*val = rz_mtu3_16bit_ch_read(priv->ch[ch_id], RZ_MTU3_TCNT);
> +static int rz_mtu3_count_write(struct counter_device *counter,
> + struct counter_count *count, const u64 val)
> +{
> + struct rz_mtu3_cnt *const priv = counter_priv(counter);
> + const size_t ch_id = RZ_MTU3_GET_HW_CH(count->id);
> + u32 ceiling;
> +
> + mutex_lock(&priv->lock);
> + if (count->id == RZ_MTU3_32_BIT_CH)
> + ceiling = priv->mtu_32bit_max;
> + else
> + ceiling = priv->mtu_16bit_max[ch_id];
> +
> + if (val > ceiling) {
> + mutex_unlock(&priv->lock);
> + return -ERANGE;
> + }
> +
> + if (count->id == RZ_MTU3_32_BIT_CH)
> + rz_mtu3_32bit_ch_write(priv->ch[0], RZ_MTU3_TCNTLW, val);
Like in count_read(), use ch_id here instead of 0 for the sake of
consistency.
> +static int rz_mtu3_count_ceiling_write(struct counter_device *counter,
> + struct counter_count *count,
> + u64 ceiling)
> +{
> + struct rz_mtu3_cnt *const priv = counter_priv(counter);
> + const size_t ch_id = RZ_MTU3_GET_HW_CH(count->id);
> +
> + switch (count->id) {
> + case RZ_MTU3_16_BIT_MTU1_CH:
> + case RZ_MTU3_16_BIT_MTU2_CH:
> + if (ceiling > U16_MAX)
> + return -ERANGE;
> + priv->mtu_16bit_max[ch_id] = ceiling;
> + break;
> + case RZ_MTU3_32_BIT_CH:
> + if (ceiling > U32_MAX)
> + return -ERANGE;
> + priv->mtu_32bit_max = ceiling;
> + break;
> + }
> +
> + mutex_lock(&priv->lock);
> + if (ceiling == 0) {
> + /* Disable counter clear source */
> + rz_mtu3_8bit_ch_write(priv->ch[ch_id], RZ_MTU3_TCR,
> + RZ_MTU3_TCR_CCLR_NONE);
Refer to our discussions in the v3 review thread regarding ceiling set
to 0; in particular, don't disable the count value ceiling but rather
limit it to a maximum value of 0.
> +static int rz_mtu3_count_enable_write(struct counter_device *counter,
> + struct counter_count *count, u8 enable)
> +{
> + struct rz_mtu3_cnt *const priv = counter_priv(counter);
> + const size_t ch_id = RZ_MTU3_GET_HW_CH(count->id);
> + struct rz_mtu3_channel *ch = priv->ch[ch_id];
> + int ret = 0;
> +
> + if (enable) {
> + pm_runtime_get_sync(ch->dev);
> + ret = rz_mtu3_initialize_counter(counter, count->id);
> + } else {
> + rz_mtu3_terminate_counter(counter, count->id);
> + pm_runtime_put(ch->dev);
> + }
Refer to our discussions in the v3 review thread regarding the "enable"
Count extension; in particular, "enable" pauses/unpauses counting.
> +static int rz_mtu3_action_read(struct counter_device *counter,
> + struct counter_count *count,
> + struct counter_synapse *synapse,
> + enum counter_synapse_action *action)
> +{
> + const size_t signal_a_id = count->synapses[0].signal->id;
> + const size_t signal_b_id = count->synapses[1].signal->id;
> + size_t signal_c_id;
> + size_t signal_d_id;
> + enum counter_function function;
> + int err;
> +
> + if (count->id != RZ_MTU3_16_BIT_MTU1_CH) {
> + signal_c_id = count->synapses[2].signal->id;
> + signal_d_id = count->synapses[3].signal->id;
> + }
The Signal ids are constants so you remove them from this function and
use preprocessor defines instead to represent SIGNAL_A_ID, SIGNAL_B_ID,
SIGNAL_C_ID, and SIGNAL_D_ID. Remember to set the Signal ids in the
rz_mtu3_signals[] array accordingly.
> +static struct counter_signal rz_mtu3_signals[] = {
> + RZ_MTU3_PHASE_SIGNAL(0, "MTU1 MTCLKA"),
> + RZ_MTU3_PHASE_SIGNAL(1, "MTU1 MTCLKB"),
> + RZ_MTU3_PHASE_SIGNAL(2, "MTU2 MTCLKC"),
> + RZ_MTU3_PHASE_SIGNAL(3, "MTU2 MTCLKD"),
> +};
The relationship of these Signals still has me somewhat confused so I'm
hoping you can help me properly ironed out my understanding. This is how
I currently understand it, so please point out any mistakes I have:
MTU1 (Channel 1):
* Pulse-Direction mode:
- MTCLKA updates count
- MTCLKB determines direction
* Quadrature x2 B:
- MTCLKA is quadrature phase A
- MTCLKB is quadrature phase B
- Any state transition on MTCLKB updates count
* Quadrature x4:
- MTCLKA is quadrature phase A
- MTCLKB is quadrature phase B
- Any state transition on either MTCLKA or MTCLKB updates count
MTU2 (Channel 2):
- Same as MTU1, but optionally can select MTCLKC and MTCLKD instead of
MTCLKA and MTCLKB respectively
* Pulse-Direction mode:
- MTCLKA(C) updates count
- MTCLKB(D) determines direction
* Quadrature x2 B:
- MTCLKA(C) is quadrature phase A
- MTCLKB(D) is quadrature phase B
- Any state transition on MTCLKB updates count
* Quadrature x4:
- MTCLKA(C) is quadrature phase A
- MTCLKB(D) is quadrature phase B
- Any state transition on either MTCLKA(C) or MTCLKB(D) updates count
MTU3 (Channel 1 and 2 cascading):
- Same as MTU2 (but count is now 32-bit)
* Pulse-Direction mode:
- MTCLKA(C) updates count
- MTCLKB(D) determines direction
* Quadrature x2 B:
- MTCLKA(C) is quadrature phase A
- MTCLKB(D) is quadrature phase B
- Any state transition on MTCLKB updates count
* Quadrature x4:
- MTCLKA(C) is quadrature phase A
- MTCLKB(D) is quadrature phase B
- Any state transition on either MTCLKA(C) or MTCLKB(D) updates count
Is my understanding correct here? Is the selection between MTCLKA/MTCLKB
and MTCLKC/MTCLKD done in software, and should we expose it in sysfs?
William Breathitt Gray
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: [PATCH v4 3/4] mfd: Add RZ/G2L MTU3 counter driver
2022-10-17 16:40 ` William Breathitt Gray
@ 2022-10-17 19:58 ` Biju Das
2022-10-17 23:02 ` William Breathitt Gray
0 siblings, 1 reply; 6+ messages in thread
From: Biju Das @ 2022-10-17 19:58 UTC (permalink / raw)
To: William Breathitt Gray
Cc: Philipp Zabel, Lee Jones, linux-iio@vger.kernel.org,
Geert Uytterhoeven, Chris Paterson, Biju Das,
Prabhakar Mahadev Lad, linux-renesas-soc@vger.kernel.org
Hi William Breathitt Gray,
> Subject: Re: [PATCH v4 3/4] mfd: Add RZ/G2L MTU3 counter driver
>
> On Mon, Oct 10, 2022 at 03:52:21PM +0100, Biju Das wrote:
> > Add RZ/G2L MTU3 counter driver. This IP supports the following phase
> > counting modes on MTU1 and MTU2 channels
> >
> > 1) 16-bit phase counting modes on MTU1 and MTU2 channels.
> > 2) 32-bit phase counting mode by cascading MTU1 and MTU2.
> >
> > This patch adds 3 counters by creating 3 logical channels
> > counter0: 16-bit phase counter on MTU1 channel
> > counter1: 16-bit phase counter on MTU2 channel
> > counter2: 32-bit phase counter by cascading MTU1 and MTU2
> > channels.
> >
> > Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
>
> Hello Biju,
>
> We discussed some changes already for v5, but I have some additional
> comments and questions below.
OK.
>
> > diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index
> > 7329971a3bdf..fa88056224c9 100644
> > --- a/drivers/mfd/Kconfig
> > +++ b/drivers/mfd/Kconfig
> > @@ -1986,6 +1986,14 @@ config MFD_RZ_MTU3
> > To compile this driver as a module, choose M here: the
> > module will be called rz-mtu3.
> >
> > +config MFD_RZ_MTU3_CNT
> > + tristate "RZ/G2L MTU3 counter driver"
>
> This is a nitpick, but include the manufacturer name in the tristate
> string for the sake of clarity: "Renesas RZ/G2L MTU3 counter driver".
>
> > + depends on MFD_RZ_MTU3 || COMPILE_TEST
>
> I noticed you include <linux/of.h> in the rz-mtu3-cnt.c file; do you
> need to depend on OF here in the Kconfig as well?
I will take out "of.h", as there is no compatible.
>
> > +static int rz_mtu3_count_read(struct counter_device *counter,
> > + struct counter_count *count, u64 *val) {
> > + struct rz_mtu3_cnt *const priv = counter_priv(counter);
> > +
> > + if (count->id == RZ_MTU3_32_BIT_CH)
> > + *val = rz_mtu3_32bit_ch_read(priv->ch[0], RZ_MTU3_TCNTLW);
> > + else
> > + *val = rz_mtu3_16bit_ch_read(priv->ch[count->id],
> RZ_MTU3_TCNT);
>
> After considering this again, I think it'll be better to match the
> structure of the rest of the functions in this driver for consistency.
> Rather than hardcoding priv->ch[0], determine the ch_id first and pass
> that instead::
OK.
>
>
> const size_t ch_id = RZ_MTU3_GET_HW_CH(count->id);
>
> if (count->id == RZ_MTU3_32_BIT_CH)
> *val = rz_mtu3_32bit_ch_read(priv->ch[ch_id],
> RZ_MTU3_TCNTLW);
> else
> *val = rz_mtu3_16bit_ch_read(priv->ch[ch_id],
> RZ_MTU3_TCNT);
>
> > +static int rz_mtu3_count_write(struct counter_device *counter,
> > + struct counter_count *count, const u64 val) {
> > + struct rz_mtu3_cnt *const priv = counter_priv(counter);
> > + const size_t ch_id = RZ_MTU3_GET_HW_CH(count->id);
> > + u32 ceiling;
> > +
> > + mutex_lock(&priv->lock);
> > + if (count->id == RZ_MTU3_32_BIT_CH)
> > + ceiling = priv->mtu_32bit_max;
> > + else
> > + ceiling = priv->mtu_16bit_max[ch_id];
> > +
> > + if (val > ceiling) {
> > + mutex_unlock(&priv->lock);
> > + return -ERANGE;
> > + }
> > +
> > + if (count->id == RZ_MTU3_32_BIT_CH)
> > + rz_mtu3_32bit_ch_write(priv->ch[0], RZ_MTU3_TCNTLW, val);
>
> Like in count_read(), use ch_id here instead of 0 for the sake of
> consistency.
>
> > +static int rz_mtu3_count_ceiling_write(struct counter_device
> *counter,
> > + struct counter_count *count,
> > + u64 ceiling)
> > +{
> > + struct rz_mtu3_cnt *const priv = counter_priv(counter);
> > + const size_t ch_id = RZ_MTU3_GET_HW_CH(count->id);
> > +
> > + switch (count->id) {
> > + case RZ_MTU3_16_BIT_MTU1_CH:
> > + case RZ_MTU3_16_BIT_MTU2_CH:
> > + if (ceiling > U16_MAX)
> > + return -ERANGE;
> > + priv->mtu_16bit_max[ch_id] = ceiling;
> > + break;
> > + case RZ_MTU3_32_BIT_CH:
> > + if (ceiling > U32_MAX)
> > + return -ERANGE;
> > + priv->mtu_32bit_max = ceiling;
> > + break;
> > + }
> > +
> > + mutex_lock(&priv->lock);
> > + if (ceiling == 0) {
> > + /* Disable counter clear source */
> > + rz_mtu3_8bit_ch_write(priv->ch[ch_id], RZ_MTU3_TCR,
> > + RZ_MTU3_TCR_CCLR_NONE);
>
> Refer to our discussions in the v3 review thread regarding ceiling set
> to 0; in particular, don't disable the count value ceiling but rather
> limit it to a maximum value of 0.
>
> > +static int rz_mtu3_count_enable_write(struct counter_device
> *counter,
> > + struct counter_count *count, u8 enable) {
> > + struct rz_mtu3_cnt *const priv = counter_priv(counter);
> > + const size_t ch_id = RZ_MTU3_GET_HW_CH(count->id);
> > + struct rz_mtu3_channel *ch = priv->ch[ch_id];
> > + int ret = 0;
> > +
> > + if (enable) {
> > + pm_runtime_get_sync(ch->dev);
> > + ret = rz_mtu3_initialize_counter(counter, count->id);
> > + } else {
> > + rz_mtu3_terminate_counter(counter, count->id);
> > + pm_runtime_put(ch->dev);
> > + }
> Refer to our discussions in the v3 review thread regarding the
> "enable"
> Count extension; in particular, "enable" pauses/unpauses counting.
>
> > +static int rz_mtu3_action_read(struct counter_device *counter,
> > + struct counter_count *count,
> > + struct counter_synapse *synapse,
> > + enum counter_synapse_action *action) {
> > + const size_t signal_a_id = count->synapses[0].signal->id;
> > + const size_t signal_b_id = count->synapses[1].signal->id;
> > + size_t signal_c_id;
> > + size_t signal_d_id;
> > + enum counter_function function;
> > + int err;
> > +
> > + if (count->id != RZ_MTU3_16_BIT_MTU1_CH) {
> > + signal_c_id = count->synapses[2].signal->id;
> > + signal_d_id = count->synapses[3].signal->id;
> > + }
>
> The Signal ids are constants so you remove them from this function and
> use preprocessor defines instead to represent SIGNAL_A_ID,
> SIGNAL_B_ID, SIGNAL_C_ID, and SIGNAL_D_ID. Remember to set the Signal
> ids in the rz_mtu3_signals[] array accordingly.
>
> > +static struct counter_signal rz_mtu3_signals[] = {
> > + RZ_MTU3_PHASE_SIGNAL(0, "MTU1 MTCLKA"),
> > + RZ_MTU3_PHASE_SIGNAL(1, "MTU1 MTCLKB"),
> > + RZ_MTU3_PHASE_SIGNAL(2, "MTU2 MTCLKC"),
> > + RZ_MTU3_PHASE_SIGNAL(3, "MTU2 MTCLKD"), };
>
> The relationship of these Signals still has me somewhat confused so
> I'm hoping you can help me properly ironed out my understanding. This
> is how I currently understand it, so please point out any mistakes I
> have:
>
> MTU1 (Channel 1):
> * Pulse-Direction mode:
> - MTCLKA updates count
> - MTCLKB determines direction
> * Quadrature x2 B:
> - MTCLKA is quadrature phase A
> - MTCLKB is quadrature phase B
> - Any state transition on MTCLKB updates count
> * Quadrature x4:
> - MTCLKA is quadrature phase A
> - MTCLKB is quadrature phase B
> - Any state transition on either MTCLKA or MTCLKB updates count
>
> MTU2 (Channel 2):
> - Same as MTU1, but optionally can select MTCLKC and MTCLKD instead
> of
> MTCLKA and MTCLKB respectively
> * Pulse-Direction mode:
> - MTCLKA(C) updates count
> - MTCLKB(D) determines direction
> * Quadrature x2 B:
> - MTCLKA(C) is quadrature phase A
> - MTCLKB(D) is quadrature phase B
> - Any state transition on MTCLKB updates count
> * Quadrature x4:
> - MTCLKA(C) is quadrature phase A
> - MTCLKB(D) is quadrature phase B
> - Any state transition on either MTCLKA(C) or MTCLKB(D) updates
> count
>
> MTU3 (Channel 1 and 2 cascading):
> - Same as MTU2 (but count is now 32-bit)
> * Pulse-Direction mode:
> - MTCLKA(C) updates count
> - MTCLKB(D) determines direction
> * Quadrature x2 B:
> - MTCLKA(C) is quadrature phase A
> - MTCLKB(D) is quadrature phase B
> - Any state transition on MTCLKB updates count
> * Quadrature x4:
> - MTCLKA(C) is quadrature phase A
> - MTCLKB(D) is quadrature phase B
> - Any state transition on either MTCLKA(C) or MTCLKB(D) updates
> count
>
> Is my understanding correct here? Is the selection between
> MTCLKA/MTCLKB and MTCLKC/MTCLKD done in software, and should we expose
> it in sysfs?
Yes, we need to expose this to sysfs. Is it same as phase mode?
Can you please provide an example, if possible how to handle this?
Cheers,
Biju
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v4 3/4] mfd: Add RZ/G2L MTU3 counter driver
2022-10-17 19:58 ` Biju Das
@ 2022-10-17 23:02 ` William Breathitt Gray
0 siblings, 0 replies; 6+ messages in thread
From: William Breathitt Gray @ 2022-10-17 23:02 UTC (permalink / raw)
To: Biju Das
Cc: Philipp Zabel, Lee Jones, linux-iio@vger.kernel.org,
Geert Uytterhoeven, Chris Paterson, Biju Das,
Prabhakar Mahadev Lad, linux-renesas-soc@vger.kernel.org
[-- Attachment #1: Type: text/plain, Size: 616 bytes --]
On Mon, Oct 17, 2022 at 07:58:54PM +0000, Biju Das wrote:
> > Is my understanding correct here? Is the selection between
> > MTCLKA/MTCLKB and MTCLKC/MTCLKD done in software, and should we expose
> > it in sysfs?
>
> Yes, we need to expose this to sysfs. Is it same as phase mode?
> Can you please provide an example, if possible how to handle this?
>
> Cheers,
> Biju
Tentatively, I think you can handle it the same way as the phase
counting mode by creating a new Counter device extension; the code
should be pretty similar except the name you give it will be different.
William Breathitt Gray
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v4 3/4] mfd: Add RZ/G2L MTU3 counter driver
2022-10-10 14:52 ` [PATCH v4 3/4] mfd: Add RZ/G2L MTU3 counter driver Biju Das
2022-10-17 16:40 ` William Breathitt Gray
@ 2022-10-25 13:50 ` Geert Uytterhoeven
2022-10-25 13:58 ` Biju Das
1 sibling, 1 reply; 6+ messages in thread
From: Geert Uytterhoeven @ 2022-10-25 13:50 UTC (permalink / raw)
To: Biju Das
Cc: William Breathitt Gray, Philipp Zabel, Lee Jones, linux-iio,
Geert Uytterhoeven, Chris Paterson, Biju Das,
Prabhakar Mahadev Lad, linux-renesas-soc
Hi Biju,
On Mon, Oct 10, 2022 at 4:53 PM Biju Das <biju.das.jz@bp.renesas.com> wrote:
> Add RZ/G2L MTU3 counter driver. This IP supports the following
> phase counting modes on MTU1 and MTU2 channels
>
> 1) 16-bit phase counting modes on MTU1 and MTU2 channels.
> 2) 32-bit phase counting mode by cascading MTU1 and MTU2.
>
> This patch adds 3 counters by creating 3 logical channels
> counter0: 16-bit phase counter on MTU1 channel
> counter1: 16-bit phase counter on MTU2 channel
> counter2: 32-bit phase counter by cascading MTU1 and MTU2
> channels.
>
> Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Thanks for your patch!
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -1986,6 +1986,14 @@ config MFD_RZ_MTU3
> To compile this driver as a module, choose M here: the
> module will be called rz-mtu3.
>
> +config MFD_RZ_MTU3_CNT
> + tristate "RZ/G2L MTU3 counter driver"
"depends on COUNTER", else it fails to link.
> + depends on MFD_RZ_MTU3 || COMPILE_TEST
> + help
> + Enable support for MTU3 counter driver found on Renesas RZ/G2L alike
> + SoCs. This IP supports both 16-bit and 32-bit phase counting mode
> + support.
> +
> config MFD_STM32_LPTIMER
> tristate "Support for STM32 Low-Power Timer"
> depends on (ARCH_STM32 && OF) || COMPILE_TEST
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: [PATCH v4 3/4] mfd: Add RZ/G2L MTU3 counter driver
2022-10-25 13:50 ` Geert Uytterhoeven
@ 2022-10-25 13:58 ` Biju Das
0 siblings, 0 replies; 6+ messages in thread
From: Biju Das @ 2022-10-25 13:58 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: William Breathitt Gray, Philipp Zabel, Lee Jones,
linux-iio@vger.kernel.org, Geert Uytterhoeven, Chris Paterson,
Biju Das, Prabhakar Mahadev Lad,
linux-renesas-soc@vger.kernel.org
Hi Geert,
Thanks for the feedback.
> Subject: Re: [PATCH v4 3/4] mfd: Add RZ/G2L MTU3 counter driver
>
> Hi Biju,
>
> On Mon, Oct 10, 2022 at 4:53 PM Biju Das <biju.das.jz@bp.renesas.com>
> wrote:
> > Add RZ/G2L MTU3 counter driver. This IP supports the following phase
> > counting modes on MTU1 and MTU2 channels
> >
> > 1) 16-bit phase counting modes on MTU1 and MTU2 channels.
> > 2) 32-bit phase counting mode by cascading MTU1 and MTU2.
> >
> > This patch adds 3 counters by creating 3 logical channels
> > counter0: 16-bit phase counter on MTU1 channel
> > counter1: 16-bit phase counter on MTU2 channel
> > counter2: 32-bit phase counter by cascading MTU1 and MTU2
> > channels.
> >
> > Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
>
> Thanks for your patch!
>
> > --- a/drivers/mfd/Kconfig
> > +++ b/drivers/mfd/Kconfig
> > @@ -1986,6 +1986,14 @@ config MFD_RZ_MTU3
> > To compile this driver as a module, choose M here: the
> > module will be called rz-mtu3.
> >
> > +config MFD_RZ_MTU3_CNT
> > + tristate "RZ/G2L MTU3 counter driver"
>
> "depends on COUNTER", else it fails to link.
OK, will add this dependency in counter/Kconfig.
As pwm/counter maintainers agreed to move the core to timer bindings.
and instantiate child devices using mfd_add_device().
Cheers,
Biju
>
> > + depends on MFD_RZ_MTU3 || COMPILE_TEST
> > + help
> > + Enable support for MTU3 counter driver found on Renesas
> RZ/G2L alike
> > + SoCs. This IP supports both 16-bit and 32-bit phase
> counting mode
> > + support.
> > +
> > config MFD_STM32_LPTIMER
> > tristate "Support for STM32 Low-Power Timer"
> > depends on (ARCH_STM32 && OF) || COMPILE_TEST
>
> Gr{oetje,eeting}s,
>
> Geert
>
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 --
> geert@linux-m68k.org
>
> In personal conversations with technical people, I call myself a
> hacker. But when I'm talking to journalists I just say "programmer" or
> something like that.
> -- Linus Torvalds
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2022-10-25 13:59 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20221010145222.1047748-1-biju.das.jz@bp.renesas.com>
2022-10-10 14:52 ` [PATCH v4 3/4] mfd: Add RZ/G2L MTU3 counter driver Biju Das
2022-10-17 16:40 ` William Breathitt Gray
2022-10-17 19:58 ` Biju Das
2022-10-17 23:02 ` William Breathitt Gray
2022-10-25 13:50 ` Geert Uytterhoeven
2022-10-25 13:58 ` Biju Das
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox