From 5f81aa76771eb43769c919064d4d5a52424857c3 Mon Sep 17 00:00:00 2001 From: Jeff Johnson Date: Sun, 2 Jun 2024 15:05:20 -0700 Subject: [PATCH 1/7] counter: ftm-quaddec: add missing MODULE_DESCRIPTION() macro make allmodconfig && make W=1 C=1 reports: WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/counter/ftm-quaddec.o Add the missing invocation of the MODULE_DESCRIPTION() macro. Signed-off-by: Jeff Johnson Link: https://lore.kernel.org/r/20240602-md-ftm-quaddec-v1-1-1bbdf705ad31@quicinc.com Signed-off-by: William Breathitt Gray --- drivers/counter/ftm-quaddec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/counter/ftm-quaddec.c b/drivers/counter/ftm-quaddec.c index aea6622a9b13..200876f3ec04 100644 --- a/drivers/counter/ftm-quaddec.c +++ b/drivers/counter/ftm-quaddec.c @@ -322,6 +322,7 @@ static struct platform_driver ftm_quaddec_driver = { module_platform_driver(ftm_quaddec_driver); +MODULE_DESCRIPTION("Flex Timer Module Quadrature decoder"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Kjeld Flarup "); MODULE_AUTHOR("Patrick Havelange "); From 10365dd4c1842d0da422b56c5aa3827db0ca08d8 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sun, 9 Jun 2024 16:49:33 -0500 Subject: [PATCH 2/7] counter: ti-eqep: implement over/underflow events This adds support to the TI eQEP counter driver for subscribing to overflow and underflow events using the counter chrdev interface. Signed-off-by: David Lechner Link: https://lore.kernel.org/r/20240609-counter-ti-eqep-over-under-events-v1-1-74fe1632f5ab@baylibre.com Signed-off-by: William Breathitt Gray --- drivers/counter/ti-eqep.c | 106 +++++++++++++++++++++++++++++++++++++- 1 file changed, 105 insertions(+), 1 deletion(-) diff --git a/drivers/counter/ti-eqep.c b/drivers/counter/ti-eqep.c index 825ae22c3ebc..a27622efebb0 100644 --- a/drivers/counter/ti-eqep.c +++ b/drivers/counter/ti-eqep.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -68,6 +69,44 @@ #define QEPCTL_UTE BIT(1) #define QEPCTL_WDE BIT(0) +#define QEINT_UTO BIT(11) +#define QEINT_IEL BIT(10) +#define QEINT_SEL BIT(9) +#define QEINT_PCM BIT(8) +#define QEINT_PCR BIT(7) +#define QEINT_PCO BIT(6) +#define QEINT_PCU BIT(5) +#define QEINT_WTO BIT(4) +#define QEINT_QDC BIT(3) +#define QEINT_PHE BIT(2) +#define QEINT_PCE BIT(1) + +#define QFLG_UTO BIT(11) +#define QFLG_IEL BIT(10) +#define QFLG_SEL BIT(9) +#define QFLG_PCM BIT(8) +#define QFLG_PCR BIT(7) +#define QFLG_PCO BIT(6) +#define QFLG_PCU BIT(5) +#define QFLG_WTO BIT(4) +#define QFLG_QDC BIT(3) +#define QFLG_PHE BIT(2) +#define QFLG_PCE BIT(1) +#define QFLG_INT BIT(0) + +#define QCLR_UTO BIT(11) +#define QCLR_IEL BIT(10) +#define QCLR_SEL BIT(9) +#define QCLR_PCM BIT(8) +#define QCLR_PCR BIT(7) +#define QCLR_PCO BIT(6) +#define QCLR_PCU BIT(5) +#define QCLR_WTO BIT(4) +#define QCLR_QDC BIT(3) +#define QCLR_PHE BIT(2) +#define QCLR_PCE BIT(1) +#define QCLR_INT BIT(0) + /* EQEP Inputs */ enum { TI_EQEP_SIGNAL_QEPA, /* QEPA/XCLK */ @@ -239,12 +278,49 @@ static int ti_eqep_action_read(struct counter_device *counter, } } +static int ti_eqep_events_configure(struct counter_device *counter) +{ + struct ti_eqep_cnt *priv = counter_priv(counter); + struct counter_event_node *event_node; + u32 qeint = 0; + + list_for_each_entry(event_node, &counter->events_list, l) { + switch (event_node->event) { + case COUNTER_EVENT_OVERFLOW: + qeint |= QEINT_PCO; + break; + case COUNTER_EVENT_UNDERFLOW: + qeint |= QEINT_PCU; + break; + } + } + + return regmap_write(priv->regmap16, QEINT, qeint); +} + +static int ti_eqep_watch_validate(struct counter_device *counter, + const struct counter_watch *watch) +{ + switch (watch->event) { + case COUNTER_EVENT_OVERFLOW: + case COUNTER_EVENT_UNDERFLOW: + if (watch->channel != 0) + return -EINVAL; + + return 0; + default: + return -EINVAL; + } +} + static const struct counter_ops ti_eqep_counter_ops = { .count_read = ti_eqep_count_read, .count_write = ti_eqep_count_write, .function_read = ti_eqep_function_read, .function_write = ti_eqep_function_write, .action_read = ti_eqep_action_read, + .events_configure = ti_eqep_events_configure, + .watch_validate = ti_eqep_watch_validate, }; static int ti_eqep_position_ceiling_read(struct counter_device *counter, @@ -355,6 +431,25 @@ static struct counter_count ti_eqep_counts[] = { }, }; +static irqreturn_t ti_eqep_irq_handler(int irq, void *dev_id) +{ + struct counter_device *counter = dev_id; + struct ti_eqep_cnt *priv = counter_priv(counter); + u32 qflg; + + regmap_read(priv->regmap16, QFLG, &qflg); + + if (qflg & QFLG_PCO) + counter_push_event(counter, COUNTER_EVENT_OVERFLOW, 0); + + if (qflg & QFLG_PCU) + counter_push_event(counter, COUNTER_EVENT_UNDERFLOW, 0); + + regmap_write(priv->regmap16, QCLR, qflg); + + return IRQ_HANDLED; +} + static const struct regmap_config ti_eqep_regmap32_config = { .name = "32-bit", .reg_bits = 32, @@ -378,7 +473,7 @@ static int ti_eqep_probe(struct platform_device *pdev) struct ti_eqep_cnt *priv; void __iomem *base; struct clk *clk; - int err; + int err, irq; counter = devm_counter_alloc(dev, sizeof(*priv)); if (!counter) @@ -399,6 +494,15 @@ static int ti_eqep_probe(struct platform_device *pdev) if (IS_ERR(priv->regmap16)) return PTR_ERR(priv->regmap16); + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + err = devm_request_threaded_irq(dev, irq, NULL, ti_eqep_irq_handler, + IRQF_ONESHOT, dev_name(dev), counter); + if (err < 0) + return dev_err_probe(dev, err, "failed to request IRQ\n"); + counter->name = dev_name(dev); counter->parent = dev; counter->ops = &ti_eqep_counter_ops; From bc4666be63bdc7c562cfb2e9ea42cdb2c444a5b2 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sun, 9 Jun 2024 15:06:15 -0500 Subject: [PATCH 3/7] counter: ti-eqep: remove unused struct member Since commit 8817c2d03a85 ("counter: ti-eqep: Convert to counter_priv() wrapper") the counter field in struct ti_eqep_cnt is not used anymore. Remove it. Signed-off-by: David Lechner Reviewed-by: Judith Mendez Link: https://lore.kernel.org/r/20240609-ti-eqep-cleanup-v1-1-9d67939c763a@baylibre.com Signed-off-by: William Breathitt Gray --- drivers/counter/ti-eqep.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/counter/ti-eqep.c b/drivers/counter/ti-eqep.c index a27622efebb0..db28fc42cf16 100644 --- a/drivers/counter/ti-eqep.c +++ b/drivers/counter/ti-eqep.c @@ -122,7 +122,6 @@ enum ti_eqep_count_func { }; struct ti_eqep_cnt { - struct counter_device counter; struct regmap *regmap32; struct regmap *regmap16; }; From 1a84aaadb06b46f044eebf0de3bd3ac77a6ec52e Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sun, 9 Jun 2024 15:06:16 -0500 Subject: [PATCH 4/7] counter: ti-eqep: remove counter_priv() wrapper The ti_eqep_count_from_counter() function is just a wrapper around counter_priv(). counter_priv() can be used directly, so we don't need the wrapper function. Remove it. Signed-off-by: David Lechner Link: https://lore.kernel.org/r/20240609-ti-eqep-cleanup-v1-2-9d67939c763a@baylibre.com Signed-off-by: William Breathitt Gray --- drivers/counter/ti-eqep.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/drivers/counter/ti-eqep.c b/drivers/counter/ti-eqep.c index db28fc42cf16..d8a789cf5417 100644 --- a/drivers/counter/ti-eqep.c +++ b/drivers/counter/ti-eqep.c @@ -126,15 +126,10 @@ struct ti_eqep_cnt { struct regmap *regmap16; }; -static struct ti_eqep_cnt *ti_eqep_count_from_counter(struct counter_device *counter) -{ - return counter_priv(counter); -} - static int ti_eqep_count_read(struct counter_device *counter, struct counter_count *count, u64 *val) { - struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); + struct ti_eqep_cnt *priv = counter_priv(counter); u32 cnt; regmap_read(priv->regmap32, QPOSCNT, &cnt); @@ -146,7 +141,7 @@ static int ti_eqep_count_read(struct counter_device *counter, static int ti_eqep_count_write(struct counter_device *counter, struct counter_count *count, u64 val) { - struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); + struct ti_eqep_cnt *priv = counter_priv(counter); u32 max; regmap_read(priv->regmap32, QPOSMAX, &max); @@ -160,7 +155,7 @@ static int ti_eqep_function_read(struct counter_device *counter, struct counter_count *count, enum counter_function *function) { - struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); + struct ti_eqep_cnt *priv = counter_priv(counter); u32 qdecctl; regmap_read(priv->regmap16, QDECCTL, &qdecctl); @@ -187,7 +182,7 @@ static int ti_eqep_function_write(struct counter_device *counter, struct counter_count *count, enum counter_function function) { - struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); + struct ti_eqep_cnt *priv = counter_priv(counter); enum ti_eqep_count_func qsrc; switch (function) { @@ -217,7 +212,7 @@ static int ti_eqep_action_read(struct counter_device *counter, struct counter_synapse *synapse, enum counter_synapse_action *action) { - struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); + struct ti_eqep_cnt *priv = counter_priv(counter); enum counter_function function; u32 qdecctl; int err; @@ -326,7 +321,7 @@ static int ti_eqep_position_ceiling_read(struct counter_device *counter, struct counter_count *count, u64 *ceiling) { - struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); + struct ti_eqep_cnt *priv = counter_priv(counter); u32 qposmax; regmap_read(priv->regmap32, QPOSMAX, &qposmax); @@ -340,7 +335,7 @@ static int ti_eqep_position_ceiling_write(struct counter_device *counter, struct counter_count *count, u64 ceiling) { - struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); + struct ti_eqep_cnt *priv = counter_priv(counter); if (ceiling != (u32)ceiling) return -ERANGE; @@ -353,7 +348,7 @@ static int ti_eqep_position_ceiling_write(struct counter_device *counter, static int ti_eqep_position_enable_read(struct counter_device *counter, struct counter_count *count, u8 *enable) { - struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); + struct ti_eqep_cnt *priv = counter_priv(counter); u32 qepctl; regmap_read(priv->regmap16, QEPCTL, &qepctl); @@ -366,7 +361,7 @@ static int ti_eqep_position_enable_read(struct counter_device *counter, static int ti_eqep_position_enable_write(struct counter_device *counter, struct counter_count *count, u8 enable) { - struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); + struct ti_eqep_cnt *priv = counter_priv(counter); regmap_write_bits(priv->regmap16, QEPCTL, QEPCTL_PHEN, enable ? -1 : 0); From 151ebcf0797b1a3ba53c8843dc21748c80e098c7 Mon Sep 17 00:00:00 2001 From: Judith Mendez Date: Wed, 12 Jun 2024 08:55:31 -0500 Subject: [PATCH 5/7] dt-bindings: counter: Add new ti,am62-eqep compatible Add new compatible ti,am62-eqep for TI K3 devices. If a device uses this compatible, require power-domains property. Since there is only one functional and interface clock for eqep, clock-names is not really required, so removed from required section, make it optional for ti,am3352-eqep compatible, and update the example. The clock-name also changed for TI K3 SoCs so do not allow clock-names property for the new compatible. Signed-off-by: Judith Mendez Acked-by: Conor Dooley Reviewed-by: David Lechner Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240612135538.2447938-2-jm@ti.com Signed-off-by: William Breathitt Gray --- .../devicetree/bindings/counter/ti-eqep.yaml | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/counter/ti-eqep.yaml b/Documentation/devicetree/bindings/counter/ti-eqep.yaml index 85f1ff83afe7..c882ab5fcf1f 100644 --- a/Documentation/devicetree/bindings/counter/ti-eqep.yaml +++ b/Documentation/devicetree/bindings/counter/ti-eqep.yaml @@ -11,7 +11,9 @@ maintainers: properties: compatible: - const: ti,am3352-eqep + enum: + - ti,am3352-eqep + - ti,am62-eqep reg: maxItems: 1 @@ -21,19 +23,35 @@ properties: maxItems: 1 clocks: - description: The clock that determines the SYSCLKOUT rate for the eQEP - peripheral. + description: The functional and interface clock that determines the clock + rate for the eQEP peripheral. maxItems: 1 clock-names: const: sysclkout + power-domains: + maxItems: 1 + +allOf: + - if: + properties: + compatible: + contains: + enum: + - ti,am62-eqep + then: + properties: + clock-names: false + + required: + - power-domains + required: - compatible - reg - interrupts - clocks - - clock-names additionalProperties: false @@ -43,7 +61,6 @@ examples: compatible = "ti,am3352-eqep"; reg = <0x180 0x80>; clocks = <&l4ls_gclk>; - clock-names = "sysclkout"; interrupts = <79>; }; From 210457b651acd61fced405cf7fef12a482932ca1 Mon Sep 17 00:00:00 2001 From: Judith Mendez Date: Wed, 12 Jun 2024 08:55:32 -0500 Subject: [PATCH 6/7] counter/ti-eqep: Add new ti-am62-eqep compatible Add new compatible for ti-am62-eqep for TI K3 SoC's. Signed-off-by: Judith Mendez Reviewed-by: David Lechner Link: https://lore.kernel.org/r/20240612135538.2447938-3-jm@ti.com Signed-off-by: William Breathitt Gray --- drivers/counter/ti-eqep.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/counter/ti-eqep.c b/drivers/counter/ti-eqep.c index d8a789cf5417..313b91456f26 100644 --- a/drivers/counter/ti-eqep.c +++ b/drivers/counter/ti-eqep.c @@ -541,6 +541,7 @@ static void ti_eqep_remove(struct platform_device *pdev) static const struct of_device_id ti_eqep_of_match[] = { { .compatible = "ti,am3352-eqep", }, + { .compatible = "ti,am62-eqep", }, { }, }; MODULE_DEVICE_TABLE(of, ti_eqep_of_match); From 988609f2aaf1c0dd1498eef6dec21c8a5fa34046 Mon Sep 17 00:00:00 2001 From: Judith Mendez Date: Wed, 12 Jun 2024 08:55:38 -0500 Subject: [PATCH 7/7] counter: ti-eqep: Allow eQEP driver to be built for K3 devices TI K3 SoC's support eQEP hardware, so add ARCH_K3 to the depends so the TI eQEP driver can be built for K3 devices. Signed-off-by: Judith Mendez Reviewed-by: David Lechner Link: https://lore.kernel.org/r/20240612135538.2447938-9-jm@ti.com Signed-off-by: William Breathitt Gray --- drivers/counter/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig index 497bc05dca4d..d30d22dfe577 100644 --- a/drivers/counter/Kconfig +++ b/drivers/counter/Kconfig @@ -138,7 +138,7 @@ config TI_ECAP_CAPTURE config TI_EQEP tristate "TI eQEP counter driver" - depends on (SOC_AM33XX || COMPILE_TEST) + depends on SOC_AM33XX || ARCH_K3 || COMPILE_TEST select REGMAP_MMIO help Select this option to enable the Texas Instruments Enhanced Quadrature