* [PATCH v7 0/4] ECAP support on TI AM62x SoC @ 2022-09-21 10:06 Julien Panis 2022-09-21 10:06 ` [PATCH v7 1/4] dt-bindings: counter: add ti,am62-ecap-capture.yaml Julien Panis ` (3 more replies) 0 siblings, 4 replies; 10+ messages in thread From: Julien Panis @ 2022-09-21 10:06 UTC (permalink / raw) To: william.gray, robh+dt, krzysztof.kozlowski+dt Cc: linux-iio, linux-kernel, devicetree, mranostay The Enhanced Capture (ECAP) module can be used to timestamp events detected on signal input pin. It can be used for time measurements of pulse train signals. ECAP module includes 4 timestamp capture registers. For all 4 sequenced timestamp capture events (0->1->2->3->0->...), edge polarity (falling/rising edge) can be selected. This driver leverages counter subsystem to : - select edge polarity for all 4 capture events (event mode) - log timestamps for each capture event Event polarity, and CAP0/1/2/3 timestamps give all the information about the input pulse train. Further information can easily be computed : period and/or duty cycle if frequency is constant, elapsed time between pulses, etc... Modifications since v6: - Leverage counter array components (RFC PATCH v5) - Remove the redundant doc of 'capture' items in sysfs-bus-counter ABI file - Add driver info to MAINTAINERS file Userspace commands : ### CLOCK SIGNAL ### cd /sys/bus/counter/devices/counter0/signal0 # Get frequency cat frequency ### INPUT SIGNAL ### cd /sys/bus/counter/devices/counter0/signal1 # Get polarity for each capture event cat polarity0 cat polarity1 cat polarity2 cat polarity3 # Set polarity for each capture event echo positive > polarity0 echo negative > polarity1 echo positive > polarity2 echo negative > polarity3 ### COUNT ### cd /sys/bus/counter/devices/counter0/count0 # Get ceiling (counter max value) cat ceiling # Reset number of overflows & current timebase counter value echo 0 > num_overflows echo 0 > count # Run ECAP echo 1 > enable # Get number of overflows & current timebase counter value cat num_overflows cat count # Get captured timestamps cat capture0 cat capture1 cat capture2 cat capture3 # Note that counter watches can also be used to get # data from userspace application # -> see tools/counter/counter_example.c # Pause ECAP echo 0 > enable Julien Panis (4): dt-bindings: counter: add ti,am62-ecap-capture.yaml Documentation: ABI: sysfs-bus-counter: add frequency & num_overflows items counter: ti-ecap-capture: capture driver support for ECAP MAINTAINERS: add TI ECAP driver info Documentation/ABI/testing/sysfs-bus-counter | 14 + .../counter/ti,am62-ecap-capture.yaml | 61 ++ MAINTAINERS | 6 + drivers/counter/Kconfig | 15 + drivers/counter/Makefile | 1 + drivers/counter/ti-ecap-capture.c | 614 ++++++++++++++++++ 6 files changed, 711 insertions(+) create mode 100644 Documentation/devicetree/bindings/counter/ti,am62-ecap-capture.yaml create mode 100644 drivers/counter/ti-ecap-capture.c -- 2.37.3 ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v7 1/4] dt-bindings: counter: add ti,am62-ecap-capture.yaml 2022-09-21 10:06 [PATCH v7 0/4] ECAP support on TI AM62x SoC Julien Panis @ 2022-09-21 10:06 ` Julien Panis 2022-09-21 10:06 ` [PATCH v7 2/4] Documentation: ABI: sysfs-bus-counter: add frequency & num_overflows items Julien Panis ` (2 subsequent siblings) 3 siblings, 0 replies; 10+ messages in thread From: Julien Panis @ 2022-09-21 10:06 UTC (permalink / raw) To: william.gray, robh+dt, krzysztof.kozlowski+dt Cc: linux-iio, linux-kernel, devicetree, mranostay This commit adds a YAML binding for TI ECAP used in capture operating mode. Signed-off-by: Julien Panis <jpanis@baylibre.com> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> --- .../counter/ti,am62-ecap-capture.yaml | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 Documentation/devicetree/bindings/counter/ti,am62-ecap-capture.yaml diff --git a/Documentation/devicetree/bindings/counter/ti,am62-ecap-capture.yaml b/Documentation/devicetree/bindings/counter/ti,am62-ecap-capture.yaml new file mode 100644 index 000000000000..4e0b2d2b303e --- /dev/null +++ b/Documentation/devicetree/bindings/counter/ti,am62-ecap-capture.yaml @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/counter/ti,am62-ecap-capture.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments Enhanced Capture (eCAP) Module + +maintainers: + - Julien Panis <jpanis@baylibre.com> + +description: | + The eCAP module resources can be used to capture timestamps + on input signal events (falling/rising edges). + +properties: + compatible: + const: ti,am62-ecap-capture + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + const: fck + + power-domains: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/soc/ti,sci_pm_domain.h> + + soc { + #address-cells = <2>; + #size-cells = <2>; + + capture@23100000 { /* eCAP in capture mode on am62x */ + compatible = "ti,am62-ecap-capture"; + reg = <0x00 0x23100000 0x00 0x100>; + interrupts = <GIC_SPI 113 IRQ_TYPE_EDGE_RISING>; + power-domains = <&k3_pds 51 TI_SCI_PD_EXCLUSIVE>; + clocks = <&k3_clks 51 0>; + clock-names = "fck"; + }; + }; -- 2.37.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v7 2/4] Documentation: ABI: sysfs-bus-counter: add frequency & num_overflows items 2022-09-21 10:06 [PATCH v7 0/4] ECAP support on TI AM62x SoC Julien Panis 2022-09-21 10:06 ` [PATCH v7 1/4] dt-bindings: counter: add ti,am62-ecap-capture.yaml Julien Panis @ 2022-09-21 10:06 ` Julien Panis 2022-09-22 2:27 ` William Breathitt Gray 2022-09-21 10:06 ` [PATCH v7 3/4] counter: ti-ecap-capture: capture driver support for ECAP Julien Panis 2022-09-21 10:06 ` [PATCH v7 4/4] MAINTAINERS: add TI ECAP driver info Julien Panis 3 siblings, 1 reply; 10+ messages in thread From: Julien Panis @ 2022-09-21 10:06 UTC (permalink / raw) To: william.gray, robh+dt, krzysztof.kozlowski+dt Cc: linux-iio, linux-kernel, devicetree, mranostay This commit adds frequency and num_overflows items to counter ABI file (e.g. for TI ECAP hardware used in capture operating mode). Signed-off-by: Julien Panis <jpanis@baylibre.com> --- Documentation/ABI/testing/sysfs-bus-counter | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-counter b/Documentation/ABI/testing/sysfs-bus-counter index 30b6e1faa6f6..aea0adc3938f 100644 --- a/Documentation/ABI/testing/sysfs-bus-counter +++ b/Documentation/ABI/testing/sysfs-bus-counter @@ -209,6 +209,12 @@ Description: both edges: Any state transition. +What: /sys/bus/counter/devices/counterX/countY/num_overflows +KernelVersion: 6.0 +Contact: jpanis@baylibre.com +Description: + This attribute indicates the number of overflows since count Y start. + What: /sys/bus/counter/devices/counterX/countY/ceiling_component_id What: /sys/bus/counter/devices/counterX/countY/floor_component_id What: /sys/bus/counter/devices/counterX/countY/count_mode_component_id @@ -219,11 +225,13 @@ What: /sys/bus/counter/devices/counterX/countY/prescaler_component_id What: /sys/bus/counter/devices/counterX/countY/preset_component_id What: /sys/bus/counter/devices/counterX/countY/preset_enable_component_id What: /sys/bus/counter/devices/counterX/countY/signalZ_action_component_id +What: /sys/bus/counter/devices/counterX/countY/num_overflows_component_id What: /sys/bus/counter/devices/counterX/signalY/cable_fault_component_id What: /sys/bus/counter/devices/counterX/signalY/cable_fault_enable_component_id What: /sys/bus/counter/devices/counterX/signalY/filter_clock_prescaler_component_id What: /sys/bus/counter/devices/counterX/signalY/index_polarity_component_id What: /sys/bus/counter/devices/counterX/signalY/synchronous_mode_component_id +What: /sys/bus/counter/devices/counterX/signalY/frequency_component_id KernelVersion: 5.16 Contact: linux-iio@vger.kernel.org Description: @@ -364,3 +372,9 @@ Description: via index_polarity. The index function (as enabled via preset_enable) is performed synchronously with the quadrature clock on the active level of the index input. + +What: /sys/bus/counter/devices/counterX/signalY/frequency +KernelVersion: 6.0 +Contact: jpanis@baylibre.com +Description: + Read-only attribute that indicates the signal Y frequency, in Hz. -- 2.37.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v7 2/4] Documentation: ABI: sysfs-bus-counter: add frequency & num_overflows items 2022-09-21 10:06 ` [PATCH v7 2/4] Documentation: ABI: sysfs-bus-counter: add frequency & num_overflows items Julien Panis @ 2022-09-22 2:27 ` William Breathitt Gray 0 siblings, 0 replies; 10+ messages in thread From: William Breathitt Gray @ 2022-09-22 2:27 UTC (permalink / raw) To: Julien Panis Cc: robh+dt, krzysztof.kozlowski+dt, linux-iio, linux-kernel, devicetree, mranostay [-- Attachment #1: Type: text/plain, Size: 2848 bytes --] On Wed, Sep 21, 2022 at 12:06:25PM +0200, Julien Panis wrote: > This commit adds frequency and num_overflows items to counter ABI file > (e.g. for TI ECAP hardware used in capture operating mode). > > Signed-off-by: Julien Panis <jpanis@baylibre.com> > --- > Documentation/ABI/testing/sysfs-bus-counter | 14 ++++++++++++++ > 1 file changed, 14 insertions(+) > > diff --git a/Documentation/ABI/testing/sysfs-bus-counter b/Documentation/ABI/testing/sysfs-bus-counter > index 30b6e1faa6f6..aea0adc3938f 100644 > --- a/Documentation/ABI/testing/sysfs-bus-counter > +++ b/Documentation/ABI/testing/sysfs-bus-counter > @@ -209,6 +209,12 @@ Description: > both edges: > Any state transition. > > +What: /sys/bus/counter/devices/counterX/countY/num_overflows > +KernelVersion: 6.0 > +Contact: jpanis@baylibre.com > +Description: > + This attribute indicates the number of overflows since count Y start. > + Update KernelVersion to "6.1" because that is the next merge target. Change Contact to "linux-iio@vger.kernel.org" since this ABI is available for all Counter drivers. Since num_overflows can be reset, replace the "since count Y start" phrase with "of Count Y" instead. > What: /sys/bus/counter/devices/counterX/countY/ceiling_component_id > What: /sys/bus/counter/devices/counterX/countY/floor_component_id > What: /sys/bus/counter/devices/counterX/countY/count_mode_component_id > @@ -219,11 +225,13 @@ What: /sys/bus/counter/devices/counterX/countY/prescaler_component_id > What: /sys/bus/counter/devices/counterX/countY/preset_component_id > What: /sys/bus/counter/devices/counterX/countY/preset_enable_component_id > What: /sys/bus/counter/devices/counterX/countY/signalZ_action_component_id > +What: /sys/bus/counter/devices/counterX/countY/num_overflows_component_id > What: /sys/bus/counter/devices/counterX/signalY/cable_fault_component_id > What: /sys/bus/counter/devices/counterX/signalY/cable_fault_enable_component_id > What: /sys/bus/counter/devices/counterX/signalY/filter_clock_prescaler_component_id > What: /sys/bus/counter/devices/counterX/signalY/index_polarity_component_id > What: /sys/bus/counter/devices/counterX/signalY/synchronous_mode_component_id > +What: /sys/bus/counter/devices/counterX/signalY/frequency_component_id > KernelVersion: 5.16 > Contact: linux-iio@vger.kernel.org > Description: > @@ -364,3 +372,9 @@ Description: > via index_polarity. The index function (as enabled via > preset_enable) is performed synchronously with the > quadrature clock on the active level of the index input. > + > +What: /sys/bus/counter/devices/counterX/signalY/frequency > +KernelVersion: 6.0 > +Contact: jpanis@baylibre.com Same changes for KernelVersion and Contact here as above. William Breathitt Gray [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v7 3/4] counter: ti-ecap-capture: capture driver support for ECAP 2022-09-21 10:06 [PATCH v7 0/4] ECAP support on TI AM62x SoC Julien Panis 2022-09-21 10:06 ` [PATCH v7 1/4] dt-bindings: counter: add ti,am62-ecap-capture.yaml Julien Panis 2022-09-21 10:06 ` [PATCH v7 2/4] Documentation: ABI: sysfs-bus-counter: add frequency & num_overflows items Julien Panis @ 2022-09-21 10:06 ` Julien Panis 2022-09-21 18:10 ` kernel test robot ` (2 more replies) 2022-09-21 10:06 ` [PATCH v7 4/4] MAINTAINERS: add TI ECAP driver info Julien Panis 3 siblings, 3 replies; 10+ messages in thread From: Julien Panis @ 2022-09-21 10:06 UTC (permalink / raw) To: william.gray, robh+dt, krzysztof.kozlowski+dt Cc: linux-iio, linux-kernel, devicetree, mranostay ECAP hardware on TI AM62x SoC supports capture feature. It can be used to timestamp events (falling/rising edges) detected on input signal. This commit adds capture driver support for ECAP hardware on AM62x SoC. In the ECAP hardware, capture pin can also be configured to be in PWM mode. Current implementation only supports capture operating mode. Hardware also supports timebase sync between multiple instances, but this driver supports simple independent capture functionality. Signed-off-by: Julien Panis <jpanis@baylibre.com> --- drivers/counter/Kconfig | 15 + drivers/counter/Makefile | 1 + drivers/counter/ti-ecap-capture.c | 614 ++++++++++++++++++++++++++++++ 3 files changed, 630 insertions(+) create mode 100644 drivers/counter/ti-ecap-capture.c diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig index 5edd155f1911..d388bf26f4dc 100644 --- a/drivers/counter/Kconfig +++ b/drivers/counter/Kconfig @@ -101,4 +101,19 @@ config INTEL_QEP To compile this driver as a module, choose M here: the module will be called intel-qep. +config TI_ECAP_CAPTURE + tristate "TI eCAP capture driver" + depends on ARCH_OMAP2PLUS || ARCH_DAVINCI_DA8XX || ARCH_KEYSTONE || ARCH_K3 || COMPILE_TEST + depends on HAS_IOMEM + select REGMAP_MMIO + help + Select this option to enable the Texas Instruments Enhanced Capture + (eCAP) driver in input mode. + + It can be used to timestamp events (falling/rising edges) detected + on ECAP input signal. + + To compile this driver as a module, choose M here: the module + will be called ti-ecap-capture. + endif # COUNTER diff --git a/drivers/counter/Makefile b/drivers/counter/Makefile index 8fde6c100ebc..b9a369e0d4fc 100644 --- a/drivers/counter/Makefile +++ b/drivers/counter/Makefile @@ -14,3 +14,4 @@ obj-$(CONFIG_TI_EQEP) += ti-eqep.o obj-$(CONFIG_FTM_QUADDEC) += ftm-quaddec.o obj-$(CONFIG_MICROCHIP_TCB_CAPTURE) += microchip-tcb-capture.o obj-$(CONFIG_INTEL_QEP) += intel-qep.o +obj-$(CONFIG_TI_ECAP_CAPTURE) += ti-ecap-capture.o diff --git a/drivers/counter/ti-ecap-capture.c b/drivers/counter/ti-ecap-capture.c new file mode 100644 index 000000000000..1c0eeb6302dd --- /dev/null +++ b/drivers/counter/ti-ecap-capture.c @@ -0,0 +1,614 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * ECAP Capture driver + * + * Copyright (C) 2022 Julien Panis <jpanis@baylibre.com> + */ + +#include <linux/atomic.h> +#include <linux/clk.h> +#include <linux/counter.h> +#include <linux/err.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> + +#define ECAP_DRV_NAME "ecap" + +/* ECAP event IDs */ +#define ECAP_CEVT1 0 +#define ECAP_CEVT2 1 +#define ECAP_CEVT3 2 +#define ECAP_CEVT4 3 +#define ECAP_CNTOVF 4 + +#define ECAP_CEVT_LAST ECAP_CEVT4 +#define ECAP_NB_CEVT (ECAP_CEVT_LAST + 1) + +#define ECAP_EVT_LAST ECAP_CNTOVF +#define ECAP_NB_EVT (ECAP_EVT_LAST + 1) + +/* Registers */ +#define ECAP_TSCNT_REG 0x00 + +#define ECAP_CAP_REG(i) (((i) << 2) + 0x08) + +#define ECAP_ECCTL_REG 0x28 +#define ECAP_CAPPOL_BIT(i) BIT((i) << 1) +#define ECAP_EV_MODE_MASK GENMASK(7, 0) +#define ECAP_CAPLDEN_BIT BIT(8) +#define ECAP_CONT_ONESHT_BIT BIT(16) +#define ECAP_STOPVALUE_MASK GENMASK(18, 17) +#define ECAP_TSCNTSTP_BIT BIT(20) +#define ECAP_SYNCO_DIS_MASK GENMASK(23, 22) +#define ECAP_CAP_APWM_BIT BIT(25) +#define ECAP_ECCTL_EN_MASK (ECAP_CAPLDEN_BIT | ECAP_TSCNTSTP_BIT) +#define ECAP_ECCTL_CFG_MASK (ECAP_SYNCO_DIS_MASK | ECAP_STOPVALUE_MASK \ + | ECAP_ECCTL_EN_MASK | ECAP_CAP_APWM_BIT \ + | ECAP_CONT_ONESHT_BIT) + +#define ECAP_ECINT_EN_FLG_REG 0x2c +#define ECAP_EVT_EN_MASK GENMASK(ECAP_NB_EVT, ECAP_NB_CEVT) +#define ECAP_EVT_FLG_BIT(i) BIT((i) + 17) + +#define ECAP_ECINT_CLR_FRC_REG 0x30 +#define ECAP_INT_CLR_BIT BIT(0) +#define ECAP_EVT_CLR_BIT(i) BIT((i) + 1) +#define ECAP_EVT_CLR_MASK GENMASK(ECAP_NB_EVT, 0) + +#define ECAP_PID_REG 0x5c + +/* + * Event modes + * One bit for each CAPx register : 1 = falling edge / 0 = rising edge + * e.g. mode = 13 = 0xd = 0b1101 + * -> falling edge for CAP1-3-4 / rising edge for CAP2 + */ +#define ECAP_EV_MODE_BIT(i) BIT(i) + +/* ECAP signals */ +#define ECAP_CLOCK_SIG 0 +#define ECAP_INPUT_SIG 1 + +static const struct regmap_config ecap_cnt_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = ECAP_PID_REG, +}; + +/** + * struct ecap_cnt_dev - device private data structure + * @enabled: device state + * @clk: device clock + * @regmap: device register map + * @nb_ovf: number of overflows since capture start + * @pm_ctx: device context for PM operations + */ +struct ecap_cnt_dev { + bool enabled; + struct clk *clk; + struct regmap *regmap; + atomic_t nb_ovf; + struct { + u8 ev_mode; + u64 time_cntr; + } pm_ctx; +}; + +static u8 ecap_cnt_capture_get_evmode(struct counter_device *counter) +{ + struct ecap_cnt_dev *ecap_dev = counter_priv(counter); + u8 ev_mode = 0; + unsigned int regval; + int i; + + pm_runtime_get_sync(counter->parent); + regmap_read(ecap_dev->regmap, ECAP_ECCTL_REG, ®val); + pm_runtime_put_sync(counter->parent); + + for (i = 0 ; i < ECAP_NB_CEVT ; i++) { + if (regval & ECAP_CAPPOL_BIT(i)) + ev_mode |= ECAP_EV_MODE_BIT(i); + } + + return ev_mode; +} + +static void ecap_cnt_capture_set_evmode(struct counter_device *counter, u8 ev_mode) +{ + struct ecap_cnt_dev *ecap_dev = counter_priv(counter); + unsigned int regval = 0; + int i; + + for (i = 0 ; i < ECAP_NB_CEVT ; i++) { + if (ev_mode & ECAP_EV_MODE_BIT(i)) + regval |= ECAP_CAPPOL_BIT(i); + } + + pm_runtime_get_sync(counter->parent); + regmap_update_bits(ecap_dev->regmap, ECAP_ECCTL_REG, ECAP_EV_MODE_MASK, regval); + pm_runtime_put_sync(counter->parent); +} + +static void ecap_cnt_capture_enable(struct counter_device *counter) +{ + struct ecap_cnt_dev *ecap_dev = counter_priv(counter); + + pm_runtime_get_sync(counter->parent); + + /* Enable interrupts on events */ + regmap_update_bits(ecap_dev->regmap, ECAP_ECINT_EN_FLG_REG, + ECAP_EVT_EN_MASK, ECAP_EVT_EN_MASK); + + /* Run counter */ + regmap_update_bits(ecap_dev->regmap, ECAP_ECCTL_REG, ECAP_ECCTL_CFG_MASK, + ECAP_SYNCO_DIS_MASK | ECAP_STOPVALUE_MASK | ECAP_ECCTL_EN_MASK); +} + +static void ecap_cnt_capture_disable(struct counter_device *counter) +{ + struct ecap_cnt_dev *ecap_dev = counter_priv(counter); + + /* Disable interrupts on events */ + regmap_update_bits(ecap_dev->regmap, ECAP_ECINT_EN_FLG_REG, ECAP_EVT_EN_MASK, 0); + + /* Stop counter */ + regmap_update_bits(ecap_dev->regmap, ECAP_ECCTL_REG, ECAP_ECCTL_EN_MASK, 0); + + pm_runtime_put_sync(counter->parent); +} + +static int ecap_cnt_count_get_val(struct counter_device *counter, unsigned int reg, u64 *val) +{ + struct ecap_cnt_dev *ecap_dev = counter_priv(counter); + unsigned int regval; + + pm_runtime_get_sync(counter->parent); + regmap_read(ecap_dev->regmap, reg, ®val); + pm_runtime_put_sync(counter->parent); + + *val = regval; + + return 0; +} + +static int ecap_cnt_count_set_val(struct counter_device *counter, unsigned int reg, u64 val) +{ + struct ecap_cnt_dev *ecap_dev = counter_priv(counter); + + pm_runtime_get_sync(counter->parent); + regmap_write(ecap_dev->regmap, reg, val); + pm_runtime_put_sync(counter->parent); + + return 0; +} + +static inline int ecap_cnt_count_read(struct counter_device *counter, + struct counter_count *count, u64 *val) +{ + return ecap_cnt_count_get_val(counter, ECAP_TSCNT_REG, val); +} + +static int ecap_cnt_count_write(struct counter_device *counter, + struct counter_count *count, u64 val) +{ + struct ecap_cnt_dev *ecap_dev = counter_priv(counter); + + if (ecap_dev->enabled) + return -EBUSY; + if (val > 0) + return -EINVAL; + + return ecap_cnt_count_set_val(counter, ECAP_TSCNT_REG, val); +} + +static int ecap_cnt_function_read(struct counter_device *counter, + struct counter_count *count, + enum counter_function *function) +{ + *function = COUNTER_FUNCTION_INCREASE; + + return 0; +} + +static int ecap_cnt_action_read(struct counter_device *counter, + struct counter_count *count, + struct counter_synapse *synapse, + enum counter_synapse_action *action) +{ + *action = (synapse->signal->id == ECAP_CLOCK_SIG) ? + COUNTER_SYNAPSE_ACTION_RISING_EDGE : + COUNTER_SYNAPSE_ACTION_NONE; + + return 0; +} + +static int ecap_cnt_watch_validate(struct counter_device *counter, + const struct counter_watch *watch) +{ + if ((watch->channel <= ECAP_CEVT_LAST && watch->event == COUNTER_EVENT_CAPTURE) || + (watch->channel == ECAP_CNTOVF && watch->event == COUNTER_EVENT_OVERFLOW)) + return 0; + + return -EINVAL; +} + +static int ecap_cnt_clk_get_freq(struct counter_device *counter, + struct counter_signal *signal, u64 *freq) +{ + struct ecap_cnt_dev *ecap_dev = counter_priv(counter); + + *freq = clk_get_rate(ecap_dev->clk); + + return 0; +} + +static int ecap_cnt_pol_read(struct counter_device *counter, + struct counter_signal *signal, + size_t idx, enum counter_signal_polarity *pol) +{ + struct ecap_cnt_dev *ecap_dev = counter_priv(counter); + + pm_runtime_get_sync(counter->parent); + *pol = regmap_test_bits(ecap_dev->regmap, ECAP_ECCTL_REG, ECAP_CAPPOL_BIT(idx)) ? + COUNTER_SIGNAL_POLARITY_NEGATIVE : + COUNTER_SIGNAL_POLARITY_POSITIVE; + pm_runtime_put_sync(counter->parent); + + return 0; +} + +static int ecap_cnt_pol_write(struct counter_device *counter, + struct counter_signal *signal, + size_t idx, enum counter_signal_polarity pol) +{ + struct ecap_cnt_dev *ecap_dev = counter_priv(counter); + + if (ecap_dev->enabled) + return -EBUSY; + + pm_runtime_get_sync(counter->parent); + if (pol == COUNTER_SIGNAL_POLARITY_NEGATIVE) + regmap_set_bits(ecap_dev->regmap, ECAP_ECCTL_REG, ECAP_CAPPOL_BIT(idx)); + else + regmap_clear_bits(ecap_dev->regmap, ECAP_ECCTL_REG, ECAP_CAPPOL_BIT(idx)); + pm_runtime_put_sync(counter->parent); + + return 0; +} + +static inline int ecap_cnt_cap_read(struct counter_device *counter, + struct counter_count *count, + size_t idx, u64 *cap) +{ + return ecap_cnt_count_get_val(counter, ECAP_CAP_REG(idx), cap); +} + +static int ecap_cnt_nb_ovf_read(struct counter_device *counter, + struct counter_count *count, u64 *val) +{ + struct ecap_cnt_dev *ecap_dev = counter_priv(counter); + + *val = atomic_read(&ecap_dev->nb_ovf); + + return 0; +} + +static int ecap_cnt_nb_ovf_write(struct counter_device *counter, + struct counter_count *count, u64 val) +{ + struct ecap_cnt_dev *ecap_dev = counter_priv(counter); + + if (ecap_dev->enabled) + return -EBUSY; + if (val > 0) + return -EINVAL; + + atomic_set(&ecap_dev->nb_ovf, val); + + return 0; +} + +static int ecap_cnt_ceiling_read(struct counter_device *counter, + struct counter_count *count, u64 *val) +{ + *val = U32_MAX; + + return 0; +} + +static int ecap_cnt_enable_read(struct counter_device *counter, + struct counter_count *count, u8 *enable) +{ + struct ecap_cnt_dev *ecap_dev = counter_priv(counter); + + *enable = ecap_dev->enabled; + + return 0; +} + +static int ecap_cnt_enable_write(struct counter_device *counter, + struct counter_count *count, u8 enable) +{ + struct ecap_cnt_dev *ecap_dev = counter_priv(counter); + + if (enable == ecap_dev->enabled) + return 0; + if (enable) + ecap_cnt_capture_enable(counter); + else + ecap_cnt_capture_disable(counter); + ecap_dev->enabled = enable; + + return 0; +} + +static const struct counter_ops ecap_cnt_ops = { + .count_read = ecap_cnt_count_read, + .count_write = ecap_cnt_count_write, + .function_read = ecap_cnt_function_read, + .action_read = ecap_cnt_action_read, + .watch_validate = ecap_cnt_watch_validate, +}; + +static const enum counter_function ecap_cnt_functions[] = { + COUNTER_FUNCTION_INCREASE, +}; + +static const enum counter_synapse_action ecap_cnt_clock_actions[] = { + COUNTER_SYNAPSE_ACTION_RISING_EDGE, +}; + +static const enum counter_synapse_action ecap_cnt_input_actions[] = { + COUNTER_SYNAPSE_ACTION_NONE, +}; + +static struct counter_comp ecap_cnt_clock_ext[] = { + COUNTER_COMP_SIGNAL_U64("frequency", ecap_cnt_clk_get_freq, NULL), +}; + +static const enum counter_signal_polarity ecap_cnt_pol_avail[] = { + COUNTER_SIGNAL_POLARITY_POSITIVE, + COUNTER_SIGNAL_POLARITY_NEGATIVE, +}; + +static DEFINE_COUNTER_ARRAY_POLARITY(ecap_cnt_pol_array, ecap_cnt_pol_avail, ECAP_NB_CEVT); + +static struct counter_comp ecap_cnt_signal_ext[] = { + COUNTER_COMP_ARRAY_POLARITY(ecap_cnt_pol_read, ecap_cnt_pol_write, ecap_cnt_pol_array), +}; + +static struct counter_signal ecap_cnt_signals[] = { + { + .id = ECAP_CLOCK_SIG, + .name = "Clock Signal", + .ext = ecap_cnt_clock_ext, + .num_ext = ARRAY_SIZE(ecap_cnt_clock_ext), + }, + { + .id = ECAP_INPUT_SIG, + .name = "Input Signal", + .ext = ecap_cnt_signal_ext, + .num_ext = ARRAY_SIZE(ecap_cnt_signal_ext), + }, +}; + +static struct counter_synapse ecap_cnt_synapses[] = { + { + .actions_list = ecap_cnt_clock_actions, + .num_actions = ARRAY_SIZE(ecap_cnt_clock_actions), + .signal = &ecap_cnt_signals[ECAP_CLOCK_SIG], + }, + { + .actions_list = ecap_cnt_input_actions, + .num_actions = ARRAY_SIZE(ecap_cnt_input_actions), + .signal = &ecap_cnt_signals[ECAP_INPUT_SIG], + }, +}; + +static DEFINE_COUNTER_ARRAY_U64(ecap_cnt_cap_array, ECAP_NB_CEVT); + +static struct counter_comp ecap_cnt_count_ext[] = { + COUNTER_COMP_COUNT_ARRAY_U64("capture", ecap_cnt_cap_read, NULL, ecap_cnt_cap_array), + COUNTER_COMP_COUNT_U64("num_overflows", ecap_cnt_nb_ovf_read, ecap_cnt_nb_ovf_write), + COUNTER_COMP_CEILING(ecap_cnt_ceiling_read, NULL), + COUNTER_COMP_ENABLE(ecap_cnt_enable_read, ecap_cnt_enable_write), +}; + +static struct counter_count ecap_cnt_counts[] = { + { + .id = 0, + .name = "Timestamp Counter", + .functions_list = ecap_cnt_functions, + .num_functions = ARRAY_SIZE(ecap_cnt_functions), + .synapses = ecap_cnt_synapses, + .num_synapses = ARRAY_SIZE(ecap_cnt_synapses), + .ext = ecap_cnt_count_ext, + .num_ext = ARRAY_SIZE(ecap_cnt_count_ext), + }, +}; + +static irqreturn_t ecap_cnt_isr(int irq, void *dev_id) +{ + struct counter_device *counter_dev = dev_id; + struct ecap_cnt_dev *ecap_dev = counter_priv(counter_dev); + unsigned int clr = 0; + unsigned int flg; + int i; + + regmap_read(ecap_dev->regmap, ECAP_ECINT_EN_FLG_REG, &flg); + + /* Check capture events */ + for (i = 0 ; i < ECAP_NB_CEVT ; i++) { + if (flg & ECAP_EVT_FLG_BIT(i)) { + counter_push_event(counter_dev, COUNTER_EVENT_CAPTURE, i); + clr |= ECAP_EVT_CLR_BIT(i); + } + } + + /* Check counter overflow */ + if (flg & ECAP_EVT_FLG_BIT(ECAP_CNTOVF)) { + atomic_inc(&ecap_dev->nb_ovf); + counter_push_event(counter_dev, COUNTER_EVENT_OVERFLOW, ECAP_CNTOVF); + clr |= ECAP_EVT_CLR_BIT(ECAP_CNTOVF); + } + + clr |= ECAP_INT_CLR_BIT; + regmap_update_bits(ecap_dev->regmap, ECAP_ECINT_CLR_FRC_REG, ECAP_EVT_CLR_MASK, clr); + + return IRQ_HANDLED; +} + +static void ecap_cnt_pm_disable(void *dev) +{ + pm_runtime_disable(dev); +} + +static int ecap_cnt_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct ecap_cnt_dev *ecap_dev; + struct counter_device *counter_dev; + void __iomem *mmio_base; + unsigned long clk_rate; + int ret; + + counter_dev = devm_counter_alloc(dev, sizeof(*ecap_dev)); + if (IS_ERR(counter_dev)) + return PTR_ERR(counter_dev); + + counter_dev->name = ECAP_DRV_NAME; + counter_dev->parent = dev; + counter_dev->ops = &ecap_cnt_ops; + counter_dev->signals = ecap_cnt_signals; + counter_dev->num_signals = ARRAY_SIZE(ecap_cnt_signals); + counter_dev->counts = ecap_cnt_counts; + counter_dev->num_counts = ARRAY_SIZE(ecap_cnt_counts); + + ecap_dev = counter_priv(counter_dev); + + ecap_dev->clk = devm_clk_get_enabled(dev, "fck"); + if (IS_ERR(ecap_dev->clk)) + return dev_err_probe(dev, PTR_ERR(ecap_dev->clk), "failed to get clock\n"); + + clk_rate = clk_get_rate(ecap_dev->clk); + if (!clk_rate) { + dev_err(dev, "failed to get clock rate\n"); + return -EINVAL; + } + + mmio_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(mmio_base)) + return PTR_ERR(mmio_base); + + ecap_dev->regmap = devm_regmap_init_mmio(dev, mmio_base, &ecap_cnt_regmap_config); + if (IS_ERR(ecap_dev->regmap)) + return dev_err_probe(dev, PTR_ERR(ecap_dev->regmap), "failed to init regmap\n"); + + ret = platform_get_irq(pdev, 0); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to get irq\n"); + + ret = devm_request_irq(dev, ret, ecap_cnt_isr, 0, pdev->name, counter_dev); + if (ret) + return dev_err_probe(dev, ret, "failed to request irq\n"); + + platform_set_drvdata(pdev, counter_dev); + + pm_runtime_enable(dev); + + /* Register a cleanup callback to care for disabling PM */ + ret = devm_add_action_or_reset(dev, ecap_cnt_pm_disable, dev); + if (ret) + return dev_err_probe(dev, ret, "failed to add pm disable action\n"); + + ecap_cnt_capture_set_evmode(counter_dev, 0); + + ret = devm_counter_add(dev, counter_dev); + if (ret) + return dev_err_probe(dev, ret, "failed to add counter\n"); + + return 0; +} + +static int ecap_cnt_remove(struct platform_device *pdev) +{ + struct counter_device *counter_dev = platform_get_drvdata(pdev); + struct ecap_cnt_dev *ecap_dev = counter_priv(counter_dev); + + if (ecap_dev->enabled) + ecap_cnt_capture_disable(counter_dev); + + return 0; +} + +static int ecap_cnt_suspend(struct device *dev) +{ + struct counter_device *counter_dev = dev_get_drvdata(dev); + struct ecap_cnt_dev *ecap_dev = counter_priv(counter_dev); + + /* If eCAP is running, stop capture then save timestamp counter */ + if (ecap_dev->enabled) { + /* + * Disabling capture has the following effects: + * - interrupts are disabled + * - loading of capture registers is disabled + * - timebase counter is stopped + */ + ecap_cnt_capture_disable(counter_dev); + ecap_cnt_count_get_val(counter_dev, ECAP_TSCNT_REG, &ecap_dev->pm_ctx.time_cntr); + } + + ecap_dev->pm_ctx.ev_mode = ecap_cnt_capture_get_evmode(counter_dev); + + clk_disable(ecap_dev->clk); + + return 0; +} + +static int ecap_cnt_resume(struct device *dev) +{ + struct counter_device *counter_dev = dev_get_drvdata(dev); + struct ecap_cnt_dev *ecap_dev = counter_priv(counter_dev); + + clk_enable(ecap_dev->clk); + + ecap_cnt_capture_set_evmode(counter_dev, ecap_dev->pm_ctx.ev_mode); + + /* If eCAP was running, restore timestamp counter then run capture */ + if (ecap_dev->enabled) { + ecap_cnt_count_set_val(counter_dev, ECAP_TSCNT_REG, ecap_dev->pm_ctx.time_cntr); + ecap_cnt_capture_enable(counter_dev); + } + + return 0; +} + +static DEFINE_SIMPLE_DEV_PM_OPS(ecap_cnt_pm_ops, ecap_cnt_suspend, ecap_cnt_resume); + +static const struct of_device_id ecap_cnt_of_match[] = { + { .compatible = "ti,am62-ecap-capture" }, + {}, +}; +MODULE_DEVICE_TABLE(of, ecap_cnt_of_match); + +static struct platform_driver ecap_cnt_driver = { + .probe = ecap_cnt_probe, + .remove = ecap_cnt_remove, + .driver = { + .name = "ecap-capture", + .of_match_table = ecap_cnt_of_match, + .pm = pm_sleep_ptr(&ecap_cnt_pm_ops), + }, +}; +module_platform_driver(ecap_cnt_driver); + +MODULE_DESCRIPTION("ECAP Capture driver"); +MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(COUNTER); -- 2.37.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v7 3/4] counter: ti-ecap-capture: capture driver support for ECAP 2022-09-21 10:06 ` [PATCH v7 3/4] counter: ti-ecap-capture: capture driver support for ECAP Julien Panis @ 2022-09-21 18:10 ` kernel test robot 2022-09-22 1:33 ` kernel test robot 2022-09-22 2:07 ` William Breathitt Gray 2 siblings, 0 replies; 10+ messages in thread From: kernel test robot @ 2022-09-21 18:10 UTC (permalink / raw) To: Julien Panis, william.gray, robh+dt, krzysztof.kozlowski+dt Cc: kbuild-all, linux-iio, linux-kernel, devicetree, mranostay Hi Julien, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on robh/for-next] [also build test WARNING on linus/master v6.0-rc6 next-20220921] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Julien-Panis/ECAP-support-on-TI-AM62x-SoC/20220921-180742 base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next config: s390-allyesconfig (https://download.01.org/0day-ci/archive/20220922/202209220145.SYlF1Xt8-lkp@intel.com/config) compiler: s390-linux-gcc (GCC) 12.1.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/intel-lab-lkp/linux/commit/f8a0bbe39ba2d6018559e92fb0c66b789387b293 git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Julien-Panis/ECAP-support-on-TI-AM62x-SoC/20220921-180742 git checkout f8a0bbe39ba2d6018559e92fb0c66b789387b293 # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=s390 SHELL=/bin/bash drivers/counter/ If you fix the issue, kindly add following tag where applicable | Reported-by: kernel test robot <lkp@intel.com> All warnings (new ones prefixed by >>): drivers/counter/ti-ecap-capture.c: In function 'ecap_cnt_watch_validate': drivers/counter/ti-ecap-capture.c:234:66: error: 'COUNTER_EVENT_CAPTURE' undeclared (first use in this function); did you mean 'COUNTER_EVENT_INDEX'? 234 | if ((watch->channel <= ECAP_CEVT_LAST && watch->event == COUNTER_EVENT_CAPTURE) || | ^~~~~~~~~~~~~~~~~~~~~ | COUNTER_EVENT_INDEX drivers/counter/ti-ecap-capture.c:234:66: note: each undeclared identifier is reported only once for each function it appears in drivers/counter/ti-ecap-capture.c: At top level: >> drivers/counter/ti-ecap-capture.c:253:47: warning: 'enum counter_signal_polarity' declared inside parameter list will not be visible outside of this definition or declaration 253 | size_t idx, enum counter_signal_polarity *pol) | ^~~~~~~~~~~~~~~~~~~~~~~ drivers/counter/ti-ecap-capture.c: In function 'ecap_cnt_pol_read': drivers/counter/ti-ecap-capture.c:259:16: error: 'COUNTER_SIGNAL_POLARITY_NEGATIVE' undeclared (first use in this function) 259 | COUNTER_SIGNAL_POLARITY_NEGATIVE : | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/counter/ti-ecap-capture.c:260:16: error: 'COUNTER_SIGNAL_POLARITY_POSITIVE' undeclared (first use in this function) 260 | COUNTER_SIGNAL_POLARITY_POSITIVE; | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/counter/ti-ecap-capture.c:258:14: error: invalid use of undefined type 'enum counter_signal_polarity' 258 | *pol = regmap_test_bits(ecap_dev->regmap, ECAP_ECCTL_REG, ECAP_CAPPOL_BIT(idx)) ? | ^ drivers/counter/ti-ecap-capture.c: At top level: drivers/counter/ti-ecap-capture.c:268:48: warning: 'enum counter_signal_polarity' declared inside parameter list will not be visible outside of this definition or declaration 268 | size_t idx, enum counter_signal_polarity pol) | ^~~~~~~~~~~~~~~~~~~~~~~ drivers/counter/ti-ecap-capture.c:268:72: error: parameter 4 ('pol') has incomplete type 268 | size_t idx, enum counter_signal_polarity pol) | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~ drivers/counter/ti-ecap-capture.c:266:12: error: function declaration isn't a prototype [-Werror=strict-prototypes] 266 | static int ecap_cnt_pol_write(struct counter_device *counter, | ^~~~~~~~~~~~~~~~~~ drivers/counter/ti-ecap-capture.c: In function 'ecap_cnt_pol_write': drivers/counter/ti-ecap-capture.c:276:20: error: 'COUNTER_SIGNAL_POLARITY_NEGATIVE' undeclared (first use in this function) 276 | if (pol == COUNTER_SIGNAL_POLARITY_NEGATIVE) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/counter/ti-ecap-capture.c: At top level: drivers/counter/ti-ecap-capture.c:375:43: error: array type has incomplete element type 'enum counter_signal_polarity' 375 | static const enum counter_signal_polarity ecap_cnt_pol_avail[] = { | ^~~~~~~~~~~~~~~~~~ drivers/counter/ti-ecap-capture.c:376:9: error: 'COUNTER_SIGNAL_POLARITY_POSITIVE' undeclared here (not in a function) 376 | COUNTER_SIGNAL_POLARITY_POSITIVE, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/counter/ti-ecap-capture.c:377:9: error: 'COUNTER_SIGNAL_POLARITY_NEGATIVE' undeclared here (not in a function) 377 | COUNTER_SIGNAL_POLARITY_NEGATIVE, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/counter/ti-ecap-capture.c:380:77: error: expected ')' before '(' token 380 | static DEFINE_COUNTER_ARRAY_POLARITY(ecap_cnt_pol_array, ecap_cnt_pol_avail, ECAP_NB_CEVT); | ^ | ) drivers/counter/ti-ecap-capture.c:383:9: error: implicit declaration of function 'COUNTER_COMP_ARRAY_POLARITY' [-Werror=implicit-function-declaration] 383 | COUNTER_COMP_ARRAY_POLARITY(ecap_cnt_pol_read, ecap_cnt_pol_write, ecap_cnt_pol_array), | ^~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/counter/ti-ecap-capture.c:383:76: error: 'ecap_cnt_pol_array' undeclared here (not in a function); did you mean 'ecap_cnt_pol_read'? 383 | COUNTER_COMP_ARRAY_POLARITY(ecap_cnt_pol_read, ecap_cnt_pol_write, ecap_cnt_pol_array), | ^~~~~~~~~~~~~~~~~~ | ecap_cnt_pol_read drivers/counter/ti-ecap-capture.c:414:52: error: expected ')' before '(' token 414 | static DEFINE_COUNTER_ARRAY_U64(ecap_cnt_cap_array, ECAP_NB_CEVT); | ^ | ) drivers/counter/ti-ecap-capture.c:417:9: error: implicit declaration of function 'COUNTER_COMP_COUNT_ARRAY_U64'; did you mean 'COUNTER_COMP_COUNT_U64'? [-Werror=implicit-function-declaration] 417 | COUNTER_COMP_COUNT_ARRAY_U64("capture", ecap_cnt_cap_read, NULL, ecap_cnt_cap_array), | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ | COUNTER_COMP_COUNT_U64 drivers/counter/ti-ecap-capture.c:417:74: error: 'ecap_cnt_cap_array' undeclared here (not in a function); did you mean 'ecap_cnt_cap_read'? 417 | COUNTER_COMP_COUNT_ARRAY_U64("capture", ecap_cnt_cap_read, NULL, ecap_cnt_cap_array), | ^~~~~~~~~~~~~~~~~~ | ecap_cnt_cap_read drivers/counter/ti-ecap-capture.c: In function 'ecap_cnt_isr': drivers/counter/ti-ecap-capture.c:449:57: error: 'COUNTER_EVENT_CAPTURE' undeclared (first use in this function); did you mean 'COUNTER_EVENT_INDEX'? 449 | counter_push_event(counter_dev, COUNTER_EVENT_CAPTURE, i); | ^~~~~~~~~~~~~~~~~~~~~ | COUNTER_EVENT_INDEX drivers/counter/ti-ecap-capture.c: At top level: drivers/counter/ti-ecap-capture.c:375:43: warning: 'ecap_cnt_pol_avail' defined but not used [-Wunused-variable] 375 | static const enum counter_signal_polarity ecap_cnt_pol_avail[] = { | ^~~~~~~~~~~~~~~~~~ cc1: some warnings being treated as errors vim +253 drivers/counter/ti-ecap-capture.c 250 251 static int ecap_cnt_pol_read(struct counter_device *counter, 252 struct counter_signal *signal, > 253 size_t idx, enum counter_signal_polarity *pol) 254 { 255 struct ecap_cnt_dev *ecap_dev = counter_priv(counter); 256 257 pm_runtime_get_sync(counter->parent); 258 *pol = regmap_test_bits(ecap_dev->regmap, ECAP_ECCTL_REG, ECAP_CAPPOL_BIT(idx)) ? 259 COUNTER_SIGNAL_POLARITY_NEGATIVE : 260 COUNTER_SIGNAL_POLARITY_POSITIVE; 261 pm_runtime_put_sync(counter->parent); 262 263 return 0; 264 } 265 -- 0-DAY CI Kernel Test Service https://01.org/lkp ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v7 3/4] counter: ti-ecap-capture: capture driver support for ECAP 2022-09-21 10:06 ` [PATCH v7 3/4] counter: ti-ecap-capture: capture driver support for ECAP Julien Panis 2022-09-21 18:10 ` kernel test robot @ 2022-09-22 1:33 ` kernel test robot 2022-09-22 2:07 ` William Breathitt Gray 2 siblings, 0 replies; 10+ messages in thread From: kernel test robot @ 2022-09-22 1:33 UTC (permalink / raw) To: Julien Panis, william.gray, robh+dt, krzysztof.kozlowski+dt Cc: kbuild-all, linux-iio, linux-kernel, devicetree, mranostay Hi Julien, Thank you for the patch! Yet something to improve: [auto build test ERROR on robh/for-next] [also build test ERROR on linus/master v6.0-rc6 next-20220921] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Julien-Panis/ECAP-support-on-TI-AM62x-SoC/20220921-180742 base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next config: s390-allyesconfig (https://download.01.org/0day-ci/archive/20220922/202209220938.I4JYSpmy-lkp@intel.com/config) compiler: s390-linux-gcc (GCC) 12.1.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/intel-lab-lkp/linux/commit/f8a0bbe39ba2d6018559e92fb0c66b789387b293 git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Julien-Panis/ECAP-support-on-TI-AM62x-SoC/20220921-180742 git checkout f8a0bbe39ba2d6018559e92fb0c66b789387b293 # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=s390 SHELL=/bin/bash drivers/ If you fix the issue, kindly add following tag where applicable | Reported-by: kernel test robot <lkp@intel.com> All errors (new ones prefixed by >>): drivers/counter/ti-ecap-capture.c: In function 'ecap_cnt_watch_validate': >> drivers/counter/ti-ecap-capture.c:234:66: error: 'COUNTER_EVENT_CAPTURE' undeclared (first use in this function); did you mean 'COUNTER_EVENT_INDEX'? 234 | if ((watch->channel <= ECAP_CEVT_LAST && watch->event == COUNTER_EVENT_CAPTURE) || | ^~~~~~~~~~~~~~~~~~~~~ | COUNTER_EVENT_INDEX drivers/counter/ti-ecap-capture.c:234:66: note: each undeclared identifier is reported only once for each function it appears in drivers/counter/ti-ecap-capture.c: At top level: drivers/counter/ti-ecap-capture.c:253:47: warning: 'enum counter_signal_polarity' declared inside parameter list will not be visible outside of this definition or declaration 253 | size_t idx, enum counter_signal_polarity *pol) | ^~~~~~~~~~~~~~~~~~~~~~~ drivers/counter/ti-ecap-capture.c: In function 'ecap_cnt_pol_read': >> drivers/counter/ti-ecap-capture.c:259:16: error: 'COUNTER_SIGNAL_POLARITY_NEGATIVE' undeclared (first use in this function) 259 | COUNTER_SIGNAL_POLARITY_NEGATIVE : | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ >> drivers/counter/ti-ecap-capture.c:260:16: error: 'COUNTER_SIGNAL_POLARITY_POSITIVE' undeclared (first use in this function) 260 | COUNTER_SIGNAL_POLARITY_POSITIVE; | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ >> drivers/counter/ti-ecap-capture.c:258:14: error: invalid use of undefined type 'enum counter_signal_polarity' 258 | *pol = regmap_test_bits(ecap_dev->regmap, ECAP_ECCTL_REG, ECAP_CAPPOL_BIT(idx)) ? | ^ drivers/counter/ti-ecap-capture.c: At top level: drivers/counter/ti-ecap-capture.c:268:48: warning: 'enum counter_signal_polarity' declared inside parameter list will not be visible outside of this definition or declaration 268 | size_t idx, enum counter_signal_polarity pol) | ^~~~~~~~~~~~~~~~~~~~~~~ >> drivers/counter/ti-ecap-capture.c:268:72: error: parameter 4 ('pol') has incomplete type 268 | size_t idx, enum counter_signal_polarity pol) | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~ >> drivers/counter/ti-ecap-capture.c:266:12: error: function declaration isn't a prototype [-Werror=strict-prototypes] 266 | static int ecap_cnt_pol_write(struct counter_device *counter, | ^~~~~~~~~~~~~~~~~~ drivers/counter/ti-ecap-capture.c: In function 'ecap_cnt_pol_write': drivers/counter/ti-ecap-capture.c:276:20: error: 'COUNTER_SIGNAL_POLARITY_NEGATIVE' undeclared (first use in this function) 276 | if (pol == COUNTER_SIGNAL_POLARITY_NEGATIVE) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/counter/ti-ecap-capture.c: At top level: >> drivers/counter/ti-ecap-capture.c:375:43: error: array type has incomplete element type 'enum counter_signal_polarity' 375 | static const enum counter_signal_polarity ecap_cnt_pol_avail[] = { | ^~~~~~~~~~~~~~~~~~ >> drivers/counter/ti-ecap-capture.c:376:9: error: 'COUNTER_SIGNAL_POLARITY_POSITIVE' undeclared here (not in a function) 376 | COUNTER_SIGNAL_POLARITY_POSITIVE, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ >> drivers/counter/ti-ecap-capture.c:377:9: error: 'COUNTER_SIGNAL_POLARITY_NEGATIVE' undeclared here (not in a function) 377 | COUNTER_SIGNAL_POLARITY_NEGATIVE, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ >> drivers/counter/ti-ecap-capture.c:380:77: error: expected ')' before '(' token 380 | static DEFINE_COUNTER_ARRAY_POLARITY(ecap_cnt_pol_array, ecap_cnt_pol_avail, ECAP_NB_CEVT); | ^ | ) >> drivers/counter/ti-ecap-capture.c:383:9: error: implicit declaration of function 'COUNTER_COMP_ARRAY_POLARITY' [-Werror=implicit-function-declaration] 383 | COUNTER_COMP_ARRAY_POLARITY(ecap_cnt_pol_read, ecap_cnt_pol_write, ecap_cnt_pol_array), | ^~~~~~~~~~~~~~~~~~~~~~~~~~~ >> drivers/counter/ti-ecap-capture.c:383:76: error: 'ecap_cnt_pol_array' undeclared here (not in a function); did you mean 'ecap_cnt_pol_read'? 383 | COUNTER_COMP_ARRAY_POLARITY(ecap_cnt_pol_read, ecap_cnt_pol_write, ecap_cnt_pol_array), | ^~~~~~~~~~~~~~~~~~ | ecap_cnt_pol_read drivers/counter/ti-ecap-capture.c:414:52: error: expected ')' before '(' token 414 | static DEFINE_COUNTER_ARRAY_U64(ecap_cnt_cap_array, ECAP_NB_CEVT); | ^ | ) >> drivers/counter/ti-ecap-capture.c:417:9: error: implicit declaration of function 'COUNTER_COMP_COUNT_ARRAY_U64'; did you mean 'COUNTER_COMP_COUNT_U64'? [-Werror=implicit-function-declaration] 417 | COUNTER_COMP_COUNT_ARRAY_U64("capture", ecap_cnt_cap_read, NULL, ecap_cnt_cap_array), | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ | COUNTER_COMP_COUNT_U64 >> drivers/counter/ti-ecap-capture.c:417:74: error: 'ecap_cnt_cap_array' undeclared here (not in a function); did you mean 'ecap_cnt_cap_read'? 417 | COUNTER_COMP_COUNT_ARRAY_U64("capture", ecap_cnt_cap_read, NULL, ecap_cnt_cap_array), | ^~~~~~~~~~~~~~~~~~ | ecap_cnt_cap_read drivers/counter/ti-ecap-capture.c: In function 'ecap_cnt_isr': drivers/counter/ti-ecap-capture.c:449:57: error: 'COUNTER_EVENT_CAPTURE' undeclared (first use in this function); did you mean 'COUNTER_EVENT_INDEX'? 449 | counter_push_event(counter_dev, COUNTER_EVENT_CAPTURE, i); | ^~~~~~~~~~~~~~~~~~~~~ | COUNTER_EVENT_INDEX drivers/counter/ti-ecap-capture.c: At top level: drivers/counter/ti-ecap-capture.c:375:43: warning: 'ecap_cnt_pol_avail' defined but not used [-Wunused-variable] 375 | static const enum counter_signal_polarity ecap_cnt_pol_avail[] = { | ^~~~~~~~~~~~~~~~~~ cc1: some warnings being treated as errors vim +234 drivers/counter/ti-ecap-capture.c 230 231 static int ecap_cnt_watch_validate(struct counter_device *counter, 232 const struct counter_watch *watch) 233 { > 234 if ((watch->channel <= ECAP_CEVT_LAST && watch->event == COUNTER_EVENT_CAPTURE) || 235 (watch->channel == ECAP_CNTOVF && watch->event == COUNTER_EVENT_OVERFLOW)) 236 return 0; 237 238 return -EINVAL; 239 } 240 241 static int ecap_cnt_clk_get_freq(struct counter_device *counter, 242 struct counter_signal *signal, u64 *freq) 243 { 244 struct ecap_cnt_dev *ecap_dev = counter_priv(counter); 245 246 *freq = clk_get_rate(ecap_dev->clk); 247 248 return 0; 249 } 250 251 static int ecap_cnt_pol_read(struct counter_device *counter, 252 struct counter_signal *signal, 253 size_t idx, enum counter_signal_polarity *pol) 254 { 255 struct ecap_cnt_dev *ecap_dev = counter_priv(counter); 256 257 pm_runtime_get_sync(counter->parent); > 258 *pol = regmap_test_bits(ecap_dev->regmap, ECAP_ECCTL_REG, ECAP_CAPPOL_BIT(idx)) ? > 259 COUNTER_SIGNAL_POLARITY_NEGATIVE : > 260 COUNTER_SIGNAL_POLARITY_POSITIVE; 261 pm_runtime_put_sync(counter->parent); 262 263 return 0; 264 } 265 > 266 static int ecap_cnt_pol_write(struct counter_device *counter, 267 struct counter_signal *signal, > 268 size_t idx, enum counter_signal_polarity pol) 269 { 270 struct ecap_cnt_dev *ecap_dev = counter_priv(counter); 271 272 if (ecap_dev->enabled) 273 return -EBUSY; 274 275 pm_runtime_get_sync(counter->parent); 276 if (pol == COUNTER_SIGNAL_POLARITY_NEGATIVE) 277 regmap_set_bits(ecap_dev->regmap, ECAP_ECCTL_REG, ECAP_CAPPOL_BIT(idx)); 278 else 279 regmap_clear_bits(ecap_dev->regmap, ECAP_ECCTL_REG, ECAP_CAPPOL_BIT(idx)); 280 pm_runtime_put_sync(counter->parent); 281 282 return 0; 283 } 284 285 static inline int ecap_cnt_cap_read(struct counter_device *counter, 286 struct counter_count *count, 287 size_t idx, u64 *cap) 288 { 289 return ecap_cnt_count_get_val(counter, ECAP_CAP_REG(idx), cap); 290 } 291 292 static int ecap_cnt_nb_ovf_read(struct counter_device *counter, 293 struct counter_count *count, u64 *val) 294 { 295 struct ecap_cnt_dev *ecap_dev = counter_priv(counter); 296 297 *val = atomic_read(&ecap_dev->nb_ovf); 298 299 return 0; 300 } 301 302 static int ecap_cnt_nb_ovf_write(struct counter_device *counter, 303 struct counter_count *count, u64 val) 304 { 305 struct ecap_cnt_dev *ecap_dev = counter_priv(counter); 306 307 if (ecap_dev->enabled) 308 return -EBUSY; 309 if (val > 0) 310 return -EINVAL; 311 312 atomic_set(&ecap_dev->nb_ovf, val); 313 314 return 0; 315 } 316 317 static int ecap_cnt_ceiling_read(struct counter_device *counter, 318 struct counter_count *count, u64 *val) 319 { 320 *val = U32_MAX; 321 322 return 0; 323 } 324 325 static int ecap_cnt_enable_read(struct counter_device *counter, 326 struct counter_count *count, u8 *enable) 327 { 328 struct ecap_cnt_dev *ecap_dev = counter_priv(counter); 329 330 *enable = ecap_dev->enabled; 331 332 return 0; 333 } 334 335 static int ecap_cnt_enable_write(struct counter_device *counter, 336 struct counter_count *count, u8 enable) 337 { 338 struct ecap_cnt_dev *ecap_dev = counter_priv(counter); 339 340 if (enable == ecap_dev->enabled) 341 return 0; 342 if (enable) 343 ecap_cnt_capture_enable(counter); 344 else 345 ecap_cnt_capture_disable(counter); 346 ecap_dev->enabled = enable; 347 348 return 0; 349 } 350 351 static const struct counter_ops ecap_cnt_ops = { 352 .count_read = ecap_cnt_count_read, 353 .count_write = ecap_cnt_count_write, 354 .function_read = ecap_cnt_function_read, 355 .action_read = ecap_cnt_action_read, 356 .watch_validate = ecap_cnt_watch_validate, 357 }; 358 359 static const enum counter_function ecap_cnt_functions[] = { 360 COUNTER_FUNCTION_INCREASE, 361 }; 362 363 static const enum counter_synapse_action ecap_cnt_clock_actions[] = { 364 COUNTER_SYNAPSE_ACTION_RISING_EDGE, 365 }; 366 367 static const enum counter_synapse_action ecap_cnt_input_actions[] = { 368 COUNTER_SYNAPSE_ACTION_NONE, 369 }; 370 371 static struct counter_comp ecap_cnt_clock_ext[] = { 372 COUNTER_COMP_SIGNAL_U64("frequency", ecap_cnt_clk_get_freq, NULL), 373 }; 374 > 375 static const enum counter_signal_polarity ecap_cnt_pol_avail[] = { > 376 COUNTER_SIGNAL_POLARITY_POSITIVE, > 377 COUNTER_SIGNAL_POLARITY_NEGATIVE, 378 }; 379 > 380 static DEFINE_COUNTER_ARRAY_POLARITY(ecap_cnt_pol_array, ecap_cnt_pol_avail, ECAP_NB_CEVT); 381 382 static struct counter_comp ecap_cnt_signal_ext[] = { > 383 COUNTER_COMP_ARRAY_POLARITY(ecap_cnt_pol_read, ecap_cnt_pol_write, ecap_cnt_pol_array), 384 }; 385 386 static struct counter_signal ecap_cnt_signals[] = { 387 { 388 .id = ECAP_CLOCK_SIG, 389 .name = "Clock Signal", 390 .ext = ecap_cnt_clock_ext, 391 .num_ext = ARRAY_SIZE(ecap_cnt_clock_ext), 392 }, 393 { 394 .id = ECAP_INPUT_SIG, 395 .name = "Input Signal", 396 .ext = ecap_cnt_signal_ext, 397 .num_ext = ARRAY_SIZE(ecap_cnt_signal_ext), 398 }, 399 }; 400 401 static struct counter_synapse ecap_cnt_synapses[] = { 402 { 403 .actions_list = ecap_cnt_clock_actions, 404 .num_actions = ARRAY_SIZE(ecap_cnt_clock_actions), 405 .signal = &ecap_cnt_signals[ECAP_CLOCK_SIG], 406 }, 407 { 408 .actions_list = ecap_cnt_input_actions, 409 .num_actions = ARRAY_SIZE(ecap_cnt_input_actions), 410 .signal = &ecap_cnt_signals[ECAP_INPUT_SIG], 411 }, 412 }; 413 414 static DEFINE_COUNTER_ARRAY_U64(ecap_cnt_cap_array, ECAP_NB_CEVT); 415 416 static struct counter_comp ecap_cnt_count_ext[] = { > 417 COUNTER_COMP_COUNT_ARRAY_U64("capture", ecap_cnt_cap_read, NULL, ecap_cnt_cap_array), 418 COUNTER_COMP_COUNT_U64("num_overflows", ecap_cnt_nb_ovf_read, ecap_cnt_nb_ovf_write), 419 COUNTER_COMP_CEILING(ecap_cnt_ceiling_read, NULL), 420 COUNTER_COMP_ENABLE(ecap_cnt_enable_read, ecap_cnt_enable_write), 421 }; 422 -- 0-DAY CI Kernel Test Service https://01.org/lkp ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v7 3/4] counter: ti-ecap-capture: capture driver support for ECAP 2022-09-21 10:06 ` [PATCH v7 3/4] counter: ti-ecap-capture: capture driver support for ECAP Julien Panis 2022-09-21 18:10 ` kernel test robot 2022-09-22 1:33 ` kernel test robot @ 2022-09-22 2:07 ` William Breathitt Gray 2 siblings, 0 replies; 10+ messages in thread From: William Breathitt Gray @ 2022-09-22 2:07 UTC (permalink / raw) To: Julien Panis Cc: robh+dt, krzysztof.kozlowski+dt, linux-iio, linux-kernel, devicetree, mranostay [-- Attachment #1: Type: text/plain, Size: 7934 bytes --] On Wed, Sep 21, 2022 at 12:06:26PM +0200, Julien Panis wrote: > ECAP hardware on TI AM62x SoC supports capture feature. It can be used > to timestamp events (falling/rising edges) detected on input signal. > > This commit adds capture driver support for ECAP hardware on AM62x SoC. > > In the ECAP hardware, capture pin can also be configured to be in > PWM mode. Current implementation only supports capture operating mode. > Hardware also supports timebase sync between multiple instances, but > this driver supports simple independent capture functionality. > > Signed-off-by: Julien Panis <jpanis@baylibre.com> Hi Julien, This driver is almost there; some comments follow below. > +static u8 ecap_cnt_capture_get_evmode(struct counter_device *counter) > +{ > + struct ecap_cnt_dev *ecap_dev = counter_priv(counter); > + u8 ev_mode = 0; > + unsigned int regval; > + int i; > + > + pm_runtime_get_sync(counter->parent); > + regmap_read(ecap_dev->regmap, ECAP_ECCTL_REG, ®val); > + pm_runtime_put_sync(counter->parent); > + > + for (i = 0 ; i < ECAP_NB_CEVT ; i++) { > + if (regval & ECAP_CAPPOL_BIT(i)) > + ev_mode |= ECAP_EV_MODE_BIT(i); > + } Looks like this for loop is just remapping the set bits in regval to ev_mode. You can use bitmap_remap() here instead to simplify this section of code. > +static void ecap_cnt_capture_set_evmode(struct counter_device *counter, u8 ev_mode) > +{ > + struct ecap_cnt_dev *ecap_dev = counter_priv(counter); > + unsigned int regval = 0; > + int i; > + > + for (i = 0 ; i < ECAP_NB_CEVT ; i++) { > + if (ev_mode & ECAP_EV_MODE_BIT(i)) > + regval |= ECAP_CAPPOL_BIT(i); > + } Use bitmap_remap() here as well (just in the reverse direction). > +static int ecap_cnt_count_write(struct counter_device *counter, > + struct counter_count *count, u64 val) > +{ > + struct ecap_cnt_dev *ecap_dev = counter_priv(counter); > + > + if (ecap_dev->enabled) > + return -EBUSY; > + if (val > 0) > + return -EINVAL; The ECAP_TSCNT_REG can be set to an arbitrary count value so there's no need to restrict val here to 0. Instead, check that val is within the ceiling value (<= U32_MAX) and return -ERANGE if it is not. > +static int ecap_cnt_watch_validate(struct counter_device *counter, > + const struct counter_watch *watch) > +{ > + if ((watch->channel <= ECAP_CEVT_LAST && watch->event == COUNTER_EVENT_CAPTURE) || > + (watch->channel == ECAP_CNTOVF && watch->event == COUNTER_EVENT_OVERFLOW)) > + return 0; > + > + return -EINVAL; COUNTER_EVENT_OVERFLOW shouldn't be on a separate channel; I'll explain why later below in the interrupt handler review. For this callback, you can separate the channel and event type checks to their own blocks: if (watch->channel > ECAP_CEVT_LAST) return -EINVAL; switch (watch->event) { case COUNTER_EVENT_CAPTURE: case COUNTER_EVENT_OVERFLOW: return 0; default: return -EINVAL; } > +static int ecap_cnt_pol_read(struct counter_device *counter, > + struct counter_signal *signal, > + size_t idx, enum counter_signal_polarity *pol) > +{ > + struct ecap_cnt_dev *ecap_dev = counter_priv(counter); > + > + pm_runtime_get_sync(counter->parent); > + *pol = regmap_test_bits(ecap_dev->regmap, ECAP_ECCTL_REG, ECAP_CAPPOL_BIT(idx)) ? > + COUNTER_SIGNAL_POLARITY_NEGATIVE : > + COUNTER_SIGNAL_POLARITY_POSITIVE; This single line is doing a lot of things so I would rather see it broken down. Save the regmap_test_bits() to a temporary local variable first before evaluating to set *pol. This allows you to move the *pol set operation to outside of the pm runtime syncs, possibly giving you a marginal improvement in latency as well. > +static inline int ecap_cnt_cap_read(struct counter_device *counter, > + struct counter_count *count, > + size_t idx, u64 *cap) > +{ > + return ecap_cnt_count_get_val(counter, ECAP_CAP_REG(idx), cap); > +} I don't remember if we've discussed this before, but if these capture registers can be set then it'll be useful to provide a corresponding ecap_cnt_cap_write() function for them as well. > +static int ecap_cnt_nb_ovf_write(struct counter_device *counter, > + struct counter_count *count, u64 val) > +{ > + struct ecap_cnt_dev *ecap_dev = counter_priv(counter); > + > + if (ecap_dev->enabled) > + return -EBUSY; > + if (val > 0) > + return -EINVAL; Similar to the count_write() callback, check that val is <= U32_MAX and return -ERANGE otherwise. > +static DEFINE_COUNTER_ARRAY_U64(ecap_cnt_cap_array, ECAP_NB_CEVT); > + > +static struct counter_comp ecap_cnt_count_ext[] = { > + COUNTER_COMP_COUNT_ARRAY_U64("capture", ecap_cnt_cap_read, NULL, ecap_cnt_cap_array), Use the DEFINE_COUNTER_ARRAY_CAPTURE() and COUNTER_COMP_ARRAY_CAPTURE() macros. > +static irqreturn_t ecap_cnt_isr(int irq, void *dev_id) > +{ > + struct counter_device *counter_dev = dev_id; > + struct ecap_cnt_dev *ecap_dev = counter_priv(counter_dev); > + unsigned int clr = 0; > + unsigned int flg; > + int i; > + > + regmap_read(ecap_dev->regmap, ECAP_ECINT_EN_FLG_REG, &flg); > + > + /* Check capture events */ > + for (i = 0 ; i < ECAP_NB_CEVT ; i++) { > + if (flg & ECAP_EVT_FLG_BIT(i)) { > + counter_push_event(counter_dev, COUNTER_EVENT_CAPTURE, i); > + clr |= ECAP_EVT_CLR_BIT(i); > + } > + } > + > + /* Check counter overflow */ > + if (flg & ECAP_EVT_FLG_BIT(ECAP_CNTOVF)) { > + atomic_inc(&ecap_dev->nb_ovf); > + counter_push_event(counter_dev, COUNTER_EVENT_OVERFLOW, ECAP_CNTOVF); COUNTER_EVENT_OVERFLOW doesn't conflict with COUNTER_EVENT_CAPTURE (they're different event types) so they can both be pushed on the same channel; in general, events of different type can share the same event channels. In this case, you should push COUNTER_EVENT_OVERFLOW to all four channels whenever you detect an overflow, so that users can receive those events regardless of which channels they are watching: counter_push_event(counter_dev, COUNTER_EVENT_OVERFLOW, 0); counter_push_event(counter_dev, COUNTER_EVENT_OVERFLOW, 1); counter_push_event(counter_dev, COUNTER_EVENT_OVERFLOW, 2); counter_push_event(counter_dev, COUNTER_EVENT_OVERFLOW, 3); There's no additional cost to pushing to these channels because events get dropped by the Counter chrdev code if the user is not watching the particular event on a channel. > +static int ecap_cnt_suspend(struct device *dev) > +{ > + struct counter_device *counter_dev = dev_get_drvdata(dev); > + struct ecap_cnt_dev *ecap_dev = counter_priv(counter_dev); > + > + /* If eCAP is running, stop capture then save timestamp counter */ > + if (ecap_dev->enabled) { > + /* > + * Disabling capture has the following effects: > + * - interrupts are disabled > + * - loading of capture registers is disabled > + * - timebase counter is stopped > + */ > + ecap_cnt_capture_disable(counter_dev); > + ecap_cnt_count_get_val(counter_dev, ECAP_TSCNT_REG, &ecap_dev->pm_ctx.time_cntr); I see time_cntr define as u64, but if count value is always <= U32_MAX you could redefine both ecap_cnt_count_get_val()'s val and time_cntr to u32 instead. > +static int ecap_cnt_resume(struct device *dev) > +{ > + struct counter_device *counter_dev = dev_get_drvdata(dev); > + struct ecap_cnt_dev *ecap_dev = counter_priv(counter_dev); > + > + clk_enable(ecap_dev->clk); > + > + ecap_cnt_capture_set_evmode(counter_dev, ecap_dev->pm_ctx.ev_mode); > + > + /* If eCAP was running, restore timestamp counter then run capture */ > + if (ecap_dev->enabled) { > + ecap_cnt_count_set_val(counter_dev, ECAP_TSCNT_REG, ecap_dev->pm_ctx.time_cntr); Same as above would apply for ecap_cnt_count_set_val() too I think. William Breathitt Gray [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v7 4/4] MAINTAINERS: add TI ECAP driver info 2022-09-21 10:06 [PATCH v7 0/4] ECAP support on TI AM62x SoC Julien Panis ` (2 preceding siblings ...) 2022-09-21 10:06 ` [PATCH v7 3/4] counter: ti-ecap-capture: capture driver support for ECAP Julien Panis @ 2022-09-21 10:06 ` Julien Panis 2022-09-22 2:19 ` William Breathitt Gray 3 siblings, 1 reply; 10+ messages in thread From: Julien Panis @ 2022-09-21 10:06 UTC (permalink / raw) To: william.gray, robh+dt, krzysztof.kozlowski+dt Cc: linux-iio, linux-kernel, devicetree, mranostay This commit adds driver info for TI ECAP used in capture operating mode. Signed-off-by: Julien Panis <jpanis@baylibre.com> --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index d4999f68bda8..fa92518b22ef 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -20322,6 +20322,12 @@ T: git git://linuxtv.org/mhadli/v4l-dvb-davinci_devices.git F: drivers/media/platform/ti/davinci/ F: include/media/davinci/ +TI ENHANCED CAPTURE (eCAP) DRIVER +R: Julien Panis <jpanis@baylibre.com> +L: linux-iio@vger.kernel.org +F: Documentation/devicetree/bindings/counter/ti,am62-ecap-capture.yaml +F: drivers/counter/ti-ecap-capture.c + TI ENHANCED QUADRATURE ENCODER PULSE (eQEP) DRIVER R: David Lechner <david@lechnology.com> L: linux-iio@vger.kernel.org -- 2.37.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v7 4/4] MAINTAINERS: add TI ECAP driver info 2022-09-21 10:06 ` [PATCH v7 4/4] MAINTAINERS: add TI ECAP driver info Julien Panis @ 2022-09-22 2:19 ` William Breathitt Gray 0 siblings, 0 replies; 10+ messages in thread From: William Breathitt Gray @ 2022-09-22 2:19 UTC (permalink / raw) To: Julien Panis Cc: robh+dt, krzysztof.kozlowski+dt, linux-iio, linux-kernel, devicetree, mranostay [-- Attachment #1: Type: text/plain, Size: 1170 bytes --] On Wed, Sep 21, 2022 at 12:06:27PM +0200, Julien Panis wrote: > This commit adds driver info for TI ECAP used in capture operating mode. > > Signed-off-by: Julien Panis <jpanis@baylibre.com> I'd like to see at least an "S: Maintained" line before I pick this up. An "M:" line would also be appreciated if available; it can be a company team address or mailing list if preferred. William Breathitt Gray > --- > MAINTAINERS | 6 ++++++ > 1 file changed, 6 insertions(+) > > diff --git a/MAINTAINERS b/MAINTAINERS > index d4999f68bda8..fa92518b22ef 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -20322,6 +20322,12 @@ T: git git://linuxtv.org/mhadli/v4l-dvb-davinci_devices.git > F: drivers/media/platform/ti/davinci/ > F: include/media/davinci/ > > +TI ENHANCED CAPTURE (eCAP) DRIVER > +R: Julien Panis <jpanis@baylibre.com> > +L: linux-iio@vger.kernel.org > +F: Documentation/devicetree/bindings/counter/ti,am62-ecap-capture.yaml > +F: drivers/counter/ti-ecap-capture.c > + > TI ENHANCED QUADRATURE ENCODER PULSE (eQEP) DRIVER > R: David Lechner <david@lechnology.com> > L: linux-iio@vger.kernel.org > -- > 2.37.3 > [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2022-09-22 2:27 UTC | newest] Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2022-09-21 10:06 [PATCH v7 0/4] ECAP support on TI AM62x SoC Julien Panis 2022-09-21 10:06 ` [PATCH v7 1/4] dt-bindings: counter: add ti,am62-ecap-capture.yaml Julien Panis 2022-09-21 10:06 ` [PATCH v7 2/4] Documentation: ABI: sysfs-bus-counter: add frequency & num_overflows items Julien Panis 2022-09-22 2:27 ` William Breathitt Gray 2022-09-21 10:06 ` [PATCH v7 3/4] counter: ti-ecap-capture: capture driver support for ECAP Julien Panis 2022-09-21 18:10 ` kernel test robot 2022-09-22 1:33 ` kernel test robot 2022-09-22 2:07 ` William Breathitt Gray 2022-09-21 10:06 ` [PATCH v7 4/4] MAINTAINERS: add TI ECAP driver info Julien Panis 2022-09-22 2:19 ` William Breathitt Gray
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).