]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
counter: ti-eqep: add direction support
authorDavid Lechner <dlechner@baylibre.com>
Sat, 11 Jan 2025 00:22:07 +0000 (18:22 -0600)
committerWilliam Breathitt Gray <wbg@kernel.org>
Wed, 5 Feb 2025 04:22:04 +0000 (13:22 +0900)
Add support for reading the direction and for emitting direction change
events to the ti-eqep counter driver.

Signed-off-by: David Lechner <dlechner@baylibre.com>
Link: https://lore.kernel.org/r/20250110-counter-ti-eqep-add-direction-support-v2-4-c6b6f96d2db9@baylibre.com
Signed-off-by: William Breathitt Gray <wbg@kernel.org>
drivers/counter/ti-eqep.c

index bc586eff0daeb52857c10fc89e4f9c0262c3441b..d21c157e531a614215b50f2271f18c998413a572 100644 (file)
 #define QCLR_PCE               BIT(1)
 #define QCLR_INT               BIT(0)
 
+#define QEPSTS_UPEVNT          BIT(7)
+#define QEPSTS_FDF             BIT(6)
+#define QEPSTS_QDF             BIT(5)
+#define QEPSTS_QDLF            BIT(4)
+#define QEPSTS_COEF            BIT(3)
+#define QEPSTS_CDEF            BIT(2)
+#define QEPSTS_FIMF            BIT(1)
+#define QEPSTS_PCEF            BIT(0)
+
 /* EQEP Inputs */
 enum {
        TI_EQEP_SIGNAL_QEPA,    /* QEPA/XCLK */
@@ -286,6 +295,9 @@ static int ti_eqep_events_configure(struct counter_device *counter)
                case COUNTER_EVENT_UNDERFLOW:
                        qeint |= QEINT_PCU;
                        break;
+               case COUNTER_EVENT_DIRECTION_CHANGE:
+                       qeint |= QEINT_QDC;
+                       break;
                }
        }
 
@@ -298,6 +310,7 @@ static int ti_eqep_watch_validate(struct counter_device *counter,
        switch (watch->event) {
        case COUNTER_EVENT_OVERFLOW:
        case COUNTER_EVENT_UNDERFLOW:
+       case COUNTER_EVENT_DIRECTION_CHANGE:
                if (watch->channel != 0)
                        return -EINVAL;
 
@@ -368,11 +381,27 @@ static int ti_eqep_position_enable_write(struct counter_device *counter,
        return 0;
 }
 
+static int ti_eqep_direction_read(struct counter_device *counter,
+                                 struct counter_count *count,
+                                 enum counter_count_direction *direction)
+{
+       struct ti_eqep_cnt *priv = counter_priv(counter);
+       u32 qepsts;
+
+       regmap_read(priv->regmap16, QEPSTS, &qepsts);
+
+       *direction = (qepsts & QEPSTS_QDF) ? COUNTER_COUNT_DIRECTION_FORWARD
+                                          : COUNTER_COUNT_DIRECTION_BACKWARD;
+
+       return 0;
+}
+
 static struct counter_comp ti_eqep_position_ext[] = {
        COUNTER_COMP_CEILING(ti_eqep_position_ceiling_read,
                             ti_eqep_position_ceiling_write),
        COUNTER_COMP_ENABLE(ti_eqep_position_enable_read,
                            ti_eqep_position_enable_write),
+       COUNTER_COMP_DIRECTION(ti_eqep_direction_read),
 };
 
 static struct counter_signal ti_eqep_signals[] = {
@@ -439,6 +468,9 @@ static irqreturn_t ti_eqep_irq_handler(int irq, void *dev_id)
        if (qflg & QFLG_PCU)
                counter_push_event(counter, COUNTER_EVENT_UNDERFLOW, 0);
 
+       if (qflg & QFLG_QDC)
+               counter_push_event(counter, COUNTER_EVENT_DIRECTION_CHANGE, 0);
+
        regmap_write(priv->regmap16, QCLR, qflg);
 
        return IRQ_HANDLED;