* [PATCH 0/2] Capture driver support for OMAP DM timer @ 2025-09-09 8:00 Gokul Praveen 2025-09-09 8:00 ` [PATCH 1/2] dt-bindings: counter: Add new ti,omap-dmtimer-cap compatible Gokul Praveen 2025-09-09 8:00 ` [PATCH 2/2] counter: ti-dmtimer-cap : capture driver support for OMAP DM timer Gokul Praveen 0 siblings, 2 replies; 12+ messages in thread From: Gokul Praveen @ 2025-09-09 8:00 UTC (permalink / raw) To: j-keerthy, vigneshr, wbg, linux-kernel, robh, krzk+dt, conor+dt, devicetree Cc: g-praveen, u-kumar1, n-francis DM timer hardware supports capture feature.It can be used to timestamp events (falling/rising edges) detected on input signal. The timer IO pin can also be configured in PWM mode but this driver supports simple independent capture functionality. Dependency: https://lore.kernel.org/all/f0d72eac-f842-4060-b197-ced20048b34b@linaro.org/ Gokul Praveen (3): dt-bindings: counter: Add new ti,omap-dmtimer-cap compatible counter: ti-dmtimer-cap : capture driver support for OMAP DM timer Enable required config for OMAP DM timer capture driver on J784S4 SOC. .../bindings/counter/ti,omap-dmtimer-cap.yaml | 34 ++ arch/arm64/configs/defconfig | 1 + drivers/counter/Kconfig | 13 + drivers/counter/Makefile | 1 + drivers/counter/ti-dmtimer-cap.c | 455 ++++++++++++++++++ 5 files changed, 504 insertions(+) create mode 100644 Documentation/devicetree/bindings/counter/ti,omap-dmtimer-cap.yaml create mode 100644 drivers/counter/ti-dmtimer-cap.c -- 2.34.1 ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/2] dt-bindings: counter: Add new ti,omap-dmtimer-cap compatible 2025-09-09 8:00 [PATCH 0/2] Capture driver support for OMAP DM timer Gokul Praveen @ 2025-09-09 8:00 ` Gokul Praveen 2025-09-10 7:08 ` Krzysztof Kozlowski 2025-09-09 8:00 ` [PATCH 2/2] counter: ti-dmtimer-cap : capture driver support for OMAP DM timer Gokul Praveen 1 sibling, 1 reply; 12+ messages in thread From: Gokul Praveen @ 2025-09-09 8:00 UTC (permalink / raw) To: j-keerthy, vigneshr, wbg, linux-kernel, robh, krzk+dt, conor+dt, devicetree Cc: g-praveen, u-kumar1, n-francis This commit adds a YAML binding for OMAP DM timer used in capture operating mode. Signed-off-by: Gokul Praveen <g-praveen@ti.com> --- .../bindings/counter/ti,omap-dmtimer-cap.yaml | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 Documentation/devicetree/bindings/counter/ti,omap-dmtimer-cap.yaml diff --git a/Documentation/devicetree/bindings/counter/ti,omap-dmtimer-cap.yaml b/Documentation/devicetree/bindings/counter/ti,omap-dmtimer-cap.yaml new file mode 100644 index 000000000000..8de9cf58aee5 --- /dev/null +++ b/Documentation/devicetree/bindings/counter/ti,omap-dmtimer-cap.yaml @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/counter/ti,omap-dmtimer-cap.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: TI dual mode timer Capture Module + +maintainers: + - Gokul Praveen <g-praveen@ti.com> + +description: + TI dual mode timer instances have an IO pin for Capture capability. + +properties: + compatible: + const: ti,omap-dmtimer-cap + + ti,timers: + description: Timer instance phandle for the Capture + $ref: /schemas/types.yaml#/definitions/phandle + +required: + - compatible + - ti,timers + +unevaluatedProperties: false + +examples: + - | + main_cap10: dmtimer-main-cap-10 { + compatible = "ti,omap-dmtimer-cap"; + ti,timers = <&main_timer10>; + }; -- 2.34.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 1/2] dt-bindings: counter: Add new ti,omap-dmtimer-cap compatible 2025-09-09 8:00 ` [PATCH 1/2] dt-bindings: counter: Add new ti,omap-dmtimer-cap compatible Gokul Praveen @ 2025-09-10 7:08 ` Krzysztof Kozlowski 2025-09-26 9:06 ` Gokul Praveen 0 siblings, 1 reply; 12+ messages in thread From: Krzysztof Kozlowski @ 2025-09-10 7:08 UTC (permalink / raw) To: Gokul Praveen, j-keerthy, vigneshr, wbg, linux-kernel, robh, krzk+dt, conor+dt, devicetree Cc: u-kumar1, n-francis On 09/09/2025 10:00, Gokul Praveen wrote: > This commit adds a YAML binding for OMAP DM timer used in Please do not use "This commit/patch/change", but imperative mood. See longer explanation here: https://elixir.bootlin.com/linux/v6.16/source/Documentation/process/submitting-patches.rst#L94 Don't use "YAML binding" - there is no such thing. Instead just describe the hardware. > capture operating mode. > > Signed-off-by: Gokul Praveen <g-praveen@ti.com> > --- > .../bindings/counter/ti,omap-dmtimer-cap.yaml | 34 +++++++++++++++++++ > 1 file changed, 34 insertions(+) > create mode 100644 Documentation/devicetree/bindings/counter/ti,omap-dmtimer-cap.yaml > > diff --git a/Documentation/devicetree/bindings/counter/ti,omap-dmtimer-cap.yaml b/Documentation/devicetree/bindings/counter/ti,omap-dmtimer-cap.yaml > new file mode 100644 > index 000000000000..8de9cf58aee5 > --- /dev/null > +++ b/Documentation/devicetree/bindings/counter/ti,omap-dmtimer-cap.yaml > @@ -0,0 +1,34 @@ > +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/counter/ti,omap-dmtimer-cap.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: TI dual mode timer Capture Module > + > +maintainers: > + - Gokul Praveen <g-praveen@ti.com> > + > +description: > + TI dual mode timer instances have an IO pin for Capture capability. > + > +properties: > + compatible: > + const: ti,omap-dmtimer-cap Missing SoC specific part. OMAP is family, no? > + > + ti,timers: > + description: Timer instance phandle for the Capture So the only resource is phandle? That's completely fake device then. NAK. > + $ref: /schemas/types.yaml#/definitions/phandle > + > +required: > + - compatible > + - ti,timers > + > +unevaluatedProperties: false > + > +examples: > + - | > + main_cap10: dmtimer-main-cap-10 { Node names should be generic. See also an explanation and list of examples (not exhaustive) in DT specification: https://devicetree-specification.readthedocs.io/en/latest/chapter2-devicetree-basics.html#generic-names-recommendation If you cannot find a name matching your device, please check in kernel sources for similar cases or you can grow the spec (via pull request to DT spec repo). Best regards, Krzysztof ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/2] dt-bindings: counter: Add new ti,omap-dmtimer-cap compatible 2025-09-10 7:08 ` Krzysztof Kozlowski @ 2025-09-26 9:06 ` Gokul Praveen 2025-10-07 6:35 ` Krzysztof Kozlowski 0 siblings, 1 reply; 12+ messages in thread From: Gokul Praveen @ 2025-09-26 9:06 UTC (permalink / raw) To: Krzysztof Kozlowski, j-keerthy, vigneshr, wbg, linux-kernel, robh, krzk+dt, conor+dt, devicetree Cc: u-kumar1, n-francis, Gokul Praveen Hi Krzysztof, Really sorry and apologies for the delay. On 10/09/25 12:38, Krzysztof Kozlowski wrote: > On 09/09/2025 10:00, Gokul Praveen wrote: >> This commit adds a YAML binding for OMAP DM timer used in > > Please do not use "This commit/patch/change", but imperative mood. See > longer explanation here: > https://elixir.bootlin.com/linux/v6.16/source/Documentation/process/submitting-patches.rst#L94 > > Don't use "YAML binding" - there is no such thing. > > Instead just describe the hardware. > Sure Krzysztof. >> capture operating mode. >> >> Signed-off-by: Gokul Praveen <g-praveen@ti.com> >> --- >> .../bindings/counter/ti,omap-dmtimer-cap.yaml | 34 +++++++++++++++++++ >> 1 file changed, 34 insertions(+) >> create mode 100644 Documentation/devicetree/bindings/counter/ti,omap-dmtimer-cap.yaml >> >> diff --git a/Documentation/devicetree/bindings/counter/ti,omap-dmtimer-cap.yaml b/Documentation/devicetree/bindings/counter/ti,omap-dmtimer-cap.yaml >> new file mode 100644 >> index 000000000000..8de9cf58aee5 >> --- /dev/null >> +++ b/Documentation/devicetree/bindings/counter/ti,omap-dmtimer-cap.yaml >> @@ -0,0 +1,34 @@ >> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause >> +%YAML 1.2 >> +--- >> +$id: http://devicetree.org/schemas/counter/ti,omap-dmtimer-cap.yaml# >> +$schema: http://devicetree.org/meta-schemas/core.yaml# >> + >> +title: TI dual mode timer Capture Module >> + >> +maintainers: >> + - Gokul Praveen <g-praveen@ti.com> >> + >> +description: >> + TI dual mode timer instances have an IO pin for Capture capability. >> + >> +properties: >> + compatible: >> + const: ti,omap-dmtimer-cap > > Missing SoC specific part. OMAP is family, no? > >> + >> + ti,timers: >> + description: Timer instance phandle for the Capture > > So the only resource is phandle? That's completely fake device then. NAK. > The OMAP Timer IP can operate in 3 modes: Timer, PWM mode or capture (mutually exclusive). The timer/ti,timer-dm.yaml file describes the timer mode of operation. It encapsulates base IP block and reg property is also part the same binding. This node represents the capture mode with phandle reference to the timer DT node. This is modeled all the same lines as how PWM functionality is implemented in pwm/ti,omap-dmtimer-pwm.yaml Now, if this needs to change, please suggest alternate. One solution is perhaps to add a new property to ti,timer-dm.yaml itself to indicate the mode of IP? >> + $ref: /schemas/types.yaml#/definitions/phandle >> + >> +required: >> + - compatible >> + - ti,timers >> + >> +unevaluatedProperties: false >> + >> +examples: >> + - | >> + main_cap10: dmtimer-main-cap-10 { > > Node names should be generic. See also an explanation and list of > examples (not exhaustive) in DT specification: > https://devicetree-specification.readthedocs.io/en/latest/chapter2-devicetree-basics.html#generic-names-recommendation > If you cannot find a name matching your device, please check in kernel > sources for similar cases or you can grow the spec (via pull request to > DT spec repo). > > Sure, I will update that Krzysztof. Regards Gokul > Best regards, > Krzysztof ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/2] dt-bindings: counter: Add new ti,omap-dmtimer-cap compatible 2025-09-26 9:06 ` Gokul Praveen @ 2025-10-07 6:35 ` Krzysztof Kozlowski 2025-10-07 9:23 ` Gokul Praveen 0 siblings, 1 reply; 12+ messages in thread From: Krzysztof Kozlowski @ 2025-10-07 6:35 UTC (permalink / raw) To: Gokul Praveen, j-keerthy, vigneshr, wbg, linux-kernel, robh, krzk+dt, conor+dt, devicetree Cc: u-kumar1, n-francis On 26/09/2025 18:06, Gokul Praveen wrote: >> >>> + >>> + ti,timers: >>> + description: Timer instance phandle for the Capture >> >> So the only resource is phandle? That's completely fake device then. NAK. >> > > > The OMAP Timer IP can operate in 3 modes: Timer, PWM mode or capture > (mutually exclusive). > The timer/ti,timer-dm.yaml file describes the timer mode of operation. > It encapsulates base IP block and reg property is also part the same > binding. > > This node represents the capture mode with phandle reference to the > timer DT node. This is modeled all the same lines as how PWM > functionality is implemented in pwm/ti,omap-dmtimer-pwm.yaml Different modes do not have their own device nodes. It is still one device, so one device node. > > Now, if this needs to change, please suggest alternate. > > One solution is perhaps to add a new property to ti,timer-dm.yaml itself > to indicate the mode of IP? Not sure, depends what this really is and how it is used. I can also imagine that consumer defines the mod of operation. Or mode of operation could be even configured runtime, thus not suitable for DT at all. Best regards, Krzysztof ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/2] dt-bindings: counter: Add new ti,omap-dmtimer-cap compatible 2025-10-07 6:35 ` Krzysztof Kozlowski @ 2025-10-07 9:23 ` Gokul Praveen 2025-10-07 9:39 ` Krzysztof Kozlowski 0 siblings, 1 reply; 12+ messages in thread From: Gokul Praveen @ 2025-10-07 9:23 UTC (permalink / raw) To: Krzysztof Kozlowski, j-keerthy, vigneshr, wbg, linux-kernel, robh, krzk+dt, conor+dt, devicetree Cc: u-kumar1, n-francis Hi Krzysztof, On 07/10/25 12:05, Krzysztof Kozlowski wrote: > On 26/09/2025 18:06, Gokul Praveen wrote: >>> >>>> + >>>> + ti,timers: >>>> + description: Timer instance phandle for the Capture >>> >>> So the only resource is phandle? That's completely fake device then. NAK. >>> >> >> >> The OMAP Timer IP can operate in 3 modes: Timer, PWM mode or capture >> (mutually exclusive). >> The timer/ti,timer-dm.yaml file describes the timer mode of operation. >> It encapsulates base IP block and reg property is also part the same >> binding. >> >> This node represents the capture mode with phandle reference to the >> timer DT node. This is modeled all the same lines as how PWM >> functionality is implemented in pwm/ti,omap-dmtimer-pwm.yaml > > Different modes do not have their own device nodes. It is still one > device, so one device node. > >> >> Now, if this needs to change, please suggest alternate. >> >> One solution is perhaps to add a new property to ti,timer-dm.yaml itself >> to indicate the mode of IP? > > Not sure, depends what this really is and how it is used. I can also > imagine that consumer defines the mod of operation. > For a timer operating in capture mode, there are no consumers actually and the only way we use it is through sysfs. Would it be good enough if I have a separate "mode" property for the dmtimer device node just like how it is done for USB as follows where the usb device node has a "dr_mode" property to decide on whether the usb should act in host, device or otg mode. &usb0 { status = "okay"; dr_mode = "host"; }; > Or mode of operation could be even configured runtime, thus not suitable > for DT at all. > > Best regards, > Krzysztof ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/2] dt-bindings: counter: Add new ti,omap-dmtimer-cap compatible 2025-10-07 9:23 ` Gokul Praveen @ 2025-10-07 9:39 ` Krzysztof Kozlowski 2025-10-07 9:49 ` Gokul Praveen 0 siblings, 1 reply; 12+ messages in thread From: Krzysztof Kozlowski @ 2025-10-07 9:39 UTC (permalink / raw) To: Gokul Praveen, j-keerthy, vigneshr, wbg, linux-kernel, robh, krzk+dt, conor+dt, devicetree Cc: u-kumar1, n-francis On 07/10/2025 18:23, Gokul Praveen wrote: > Hi Krzysztof, > > > On 07/10/25 12:05, Krzysztof Kozlowski wrote: >> On 26/09/2025 18:06, Gokul Praveen wrote: >>>> >>>>> + >>>>> + ti,timers: >>>>> + description: Timer instance phandle for the Capture >>>> >>>> So the only resource is phandle? That's completely fake device then. NAK. >>>> >>> >>> >>> The OMAP Timer IP can operate in 3 modes: Timer, PWM mode or capture >>> (mutually exclusive). >>> The timer/ti,timer-dm.yaml file describes the timer mode of operation. >>> It encapsulates base IP block and reg property is also part the same >>> binding. >>> >>> This node represents the capture mode with phandle reference to the >>> timer DT node. This is modeled all the same lines as how PWM >>> functionality is implemented in pwm/ti,omap-dmtimer-pwm.yaml >> >> Different modes do not have their own device nodes. It is still one >> device, so one device node. >> >>> >>> Now, if this needs to change, please suggest alternate. >>> >>> One solution is perhaps to add a new property to ti,timer-dm.yaml itself >>> to indicate the mode of IP? >> >> Not sure, depends what this really is and how it is used. I can also >> imagine that consumer defines the mod of operation. >> > > For a timer operating in capture mode, there are no consumers actually > and the only way we use it is through sysfs. > > Would it be good enough if I have a separate "mode" property for the > dmtimer device node just like how it is done for USB as follows where > the usb device node has a "dr_mode" property to decide on whether the > usb should act in host, device or otg mode. No, because of all my other comments in previous email. Best regards, Krzysztof ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/2] dt-bindings: counter: Add new ti,omap-dmtimer-cap compatible 2025-10-07 9:39 ` Krzysztof Kozlowski @ 2025-10-07 9:49 ` Gokul Praveen 2025-10-07 14:32 ` Krzysztof Kozlowski 0 siblings, 1 reply; 12+ messages in thread From: Gokul Praveen @ 2025-10-07 9:49 UTC (permalink / raw) To: Krzysztof Kozlowski, j-keerthy, vigneshr, wbg, linux-kernel, robh, krzk+dt, conor+dt, devicetree Cc: u-kumar1, n-francis, Gokul Praveen Hi Krzysztof, On 07/10/25 15:09, Krzysztof Kozlowski wrote: > On 07/10/2025 18:23, Gokul Praveen wrote: >> Hi Krzysztof, >> >> >> On 07/10/25 12:05, Krzysztof Kozlowski wrote: >>> On 26/09/2025 18:06, Gokul Praveen wrote: >>>>> >>>>>> + >>>>>> + ti,timers: >>>>>> + description: Timer instance phandle for the Capture >>>>> >>>>> So the only resource is phandle? That's completely fake device then. NAK. >>>>> >>>> >>>> >>>> The OMAP Timer IP can operate in 3 modes: Timer, PWM mode or capture >>>> (mutually exclusive). >>>> The timer/ti,timer-dm.yaml file describes the timer mode of operation. >>>> It encapsulates base IP block and reg property is also part the same >>>> binding. >>>> >>>> This node represents the capture mode with phandle reference to the >>>> timer DT node. This is modeled all the same lines as how PWM >>>> functionality is implemented in pwm/ti,omap-dmtimer-pwm.yaml >>> >>> Different modes do not have their own device nodes. It is still one >>> device, so one device node. >>> >>>> >>>> Now, if this needs to change, please suggest alternate. >>>> >>>> One solution is perhaps to add a new property to ti,timer-dm.yaml itself >>>> to indicate the mode of IP? >>> >>> Not sure, depends what this really is and how it is used. I can also >>> imagine that consumer defines the mod of operation. >>> >> >> For a timer operating in capture mode, there are no consumers actually >> and the only way we use it is through sysfs. >> >> Would it be good enough if I have a separate "mode" property for the >> dmtimer device node just like how it is done for USB as follows where >> the usb device node has a "dr_mode" property to decide on whether the >> usb should act in host, device or otg mode. > > > No, because of all my other comments in previous email. > > Will having a separate sysfs property for enabling capture mode in dmtimer be a viable solution, which will then eliminate the need for a device tree property? It would be great to hear your feedback on this, krzysztof. Best regards Gokul > Best regards, > Krzysztof ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/2] dt-bindings: counter: Add new ti,omap-dmtimer-cap compatible 2025-10-07 9:49 ` Gokul Praveen @ 2025-10-07 14:32 ` Krzysztof Kozlowski 0 siblings, 0 replies; 12+ messages in thread From: Krzysztof Kozlowski @ 2025-10-07 14:32 UTC (permalink / raw) To: Gokul Praveen, j-keerthy, vigneshr, wbg, linux-kernel, robh, krzk+dt, conor+dt, devicetree Cc: u-kumar1, n-francis On 07/10/2025 18:49, Gokul Praveen wrote: > Hi Krzysztof, > > On 07/10/25 15:09, Krzysztof Kozlowski wrote: >> On 07/10/2025 18:23, Gokul Praveen wrote: >>> Hi Krzysztof, >>> >>> >>> On 07/10/25 12:05, Krzysztof Kozlowski wrote: >>>> On 26/09/2025 18:06, Gokul Praveen wrote: >>>>>> >>>>>>> + >>>>>>> + ti,timers: >>>>>>> + description: Timer instance phandle for the Capture >>>>>> >>>>>> So the only resource is phandle? That's completely fake device then. NAK. >>>>>> >>>>> >>>>> >>>>> The OMAP Timer IP can operate in 3 modes: Timer, PWM mode or capture >>>>> (mutually exclusive). >>>>> The timer/ti,timer-dm.yaml file describes the timer mode of operation. >>>>> It encapsulates base IP block and reg property is also part the same >>>>> binding. >>>>> >>>>> This node represents the capture mode with phandle reference to the >>>>> timer DT node. This is modeled all the same lines as how PWM >>>>> functionality is implemented in pwm/ti,omap-dmtimer-pwm.yaml >>>> >>>> Different modes do not have their own device nodes. It is still one >>>> device, so one device node. >>>> >>>>> >>>>> Now, if this needs to change, please suggest alternate. >>>>> >>>>> One solution is perhaps to add a new property to ti,timer-dm.yaml itself >>>>> to indicate the mode of IP? >>>> >>>> Not sure, depends what this really is and how it is used. I can also >>>> imagine that consumer defines the mod of operation. >>>> >>> >>> For a timer operating in capture mode, there are no consumers actually >>> and the only way we use it is through sysfs. >>> >>> Would it be good enough if I have a separate "mode" property for the >>> dmtimer device node just like how it is done for USB as follows where >>> the usb device node has a "dr_mode" property to decide on whether the >>> usb should act in host, device or otg mode. >> >> >> No, because of all my other comments in previous email. >> >> > Will having a separate sysfs property for enabling capture mode in > dmtimer be a viable solution, which will then eliminate the need for a > device tree property? > > It would be great to hear your feedback on this, krzysztof. Could be, if this can be a runtime property. My questions and doubts are indeed not a very clear guidance, partially because I don't know all use cases for this hardware. Lack of PWM consumer is already an indication for the driver to configure it in other mode, for example. But think rather why choice of mode would be board-level static configuration. If you cannot answer that, then it should not be a DT property most likely. Best regards, Krzysztof ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 2/2] counter: ti-dmtimer-cap : capture driver support for OMAP DM timer 2025-09-09 8:00 [PATCH 0/2] Capture driver support for OMAP DM timer Gokul Praveen 2025-09-09 8:00 ` [PATCH 1/2] dt-bindings: counter: Add new ti,omap-dmtimer-cap compatible Gokul Praveen @ 2025-09-09 8:00 ` Gokul Praveen 2025-09-09 14:58 ` Andrew Davis 2025-09-10 6:39 ` kernel test robot 1 sibling, 2 replies; 12+ messages in thread From: Gokul Praveen @ 2025-09-09 8:00 UTC (permalink / raw) To: j-keerthy, vigneshr, wbg, linux-kernel, robh, krzk+dt, conor+dt, devicetree Cc: g-praveen, u-kumar1, n-francis Enable capture driver support for OMAP DM timer hardware. DM timer hardware supports capture feature.It can be used to timestamp events (falling/rising edges) detected on input signal. The timer IO pin can also be configured in PWM mode but this driver supports simple independent capture functionality. It is assumed that the capture signal is active else both duty cycle and period returned by driver will not be valid. Signed-off-by: Gokul Praveen <g-praveen@ti.com> --- BOOT LOGS: https://gist.github.com/GokulPraveen2001/581fa07b2e93f30dea9f6188a97b944b TIMER CAPTURE DTSO: &{/} { main_cap10: dmtimer-main-cap-10 { compatible = "ti,omap-dmtimer-cap"; ti,timers = <&main_timer10>; pinctrl-0 = <&maindmtimer1_pins_default>,<&main_timer10_ctrl_config>; pinctrl-names = "default"; }; }; &main_timer10{ status = "okay"; }; /*MAIN_TIMERIO1*/ &main_pmx0 { maindmtimer1_pins_default: maindmtimer1-default-pins { pinctrl-single,pins = < J784S4_IOPAD(0x0ec, PIN_INPUT, 0) /* (AN37) TIMER_IO1:Input mode for Capture*/ >; }; }; /*Sets in CAP mode using MAIN TIMER IOX(X=1 here) CTRL MMR REGISTERS*/ &main_timerio_input { main_timer10_ctrl_config: main-timer10-ctrl-config { pinctrl-single,pins = < J784S4_IOPAD(0x28,0,0x1)>; /* MAIN_TIMER_10 will use MAIN_TIMERIO1 pin(maindmtimer1-default-pins) for capture*/ }; }; --- drivers/counter/Kconfig | 13 + drivers/counter/Makefile | 1 + drivers/counter/ti-dmtimer-cap.c | 455 +++++++++++++++++++++++++++++++ 3 files changed, 469 insertions(+) create mode 100644 drivers/counter/ti-dmtimer-cap.c diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig index d30d22dfe577..bec07cf15779 100644 --- a/drivers/counter/Kconfig +++ b/drivers/counter/Kconfig @@ -121,6 +121,19 @@ config STM32_TIMER_CNT To compile this driver as a module, choose M here: the module will be called stm32-timer-cnt. +config TI_DMTIMER_CAPTURE + tristate "OMAP Dual-Mode Timer Capture support" + depends on OMAP_DM_TIMER || COMPILE_TEST + help + Select this option to use the Texas Instruments OMAP DM Timer + driver in capture mode. + + It can be used to timestamp events (falling/rising edges) detected + on Timer input signal. + + To compile this driver as a module, choose M here: the module + will be called ti-dmtimer-cap. + config TI_ECAP_CAPTURE tristate "TI eCAP capture driver" depends on ARCH_OMAP2PLUS || ARCH_DAVINCI_DA8XX || ARCH_KEYSTONE || ARCH_K3 || COMPILE_TEST diff --git a/drivers/counter/Makefile b/drivers/counter/Makefile index fa3c1d08f706..7c2d226fe984 100644 --- a/drivers/counter/Makefile +++ b/drivers/counter/Makefile @@ -17,3 +17,4 @@ 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 +obj-$(CONFIG_TI_DMTIMER_CAPTURE) +=ti-dmtimer-cap.o diff --git a/drivers/counter/ti-dmtimer-cap.c b/drivers/counter/ti-dmtimer-cap.c new file mode 100644 index 000000000000..dedfb15faa10 --- /dev/null +++ b/drivers/counter/ti-dmtimer-cap.c @@ -0,0 +1,455 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * DM timer Capture Driver + */ + +#include <clocksource/timer-ti-dm.h> +#include <linux/atomic.h> +#include <linux/counter.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/mutex.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/platform_data/dmtimer-omap.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/slab.h> +#include <linux/time.h> + +#define TIMER_DRV_NAME "CAP_OMAP_DMTIMER" +/* Timer signals */ +#define TIMER_CLOCK_SIG 0 +#define TIMER_INPUT_SIG 1 + +/** + * struct cap_omap_dmtimer_counter - Structure representing a cap counter + * corresponding to omap dm timer. + * @counter: Capture counter + * @enabled: Tracks the enable status of omap dm timer. + * @mutex: Mutex to protect cap apply state + * @dm_timer: Pointer to omap dm timer. + * @pdata: Pointer to omap dm timer ops. + * @dm_timer_pdev: Pointer to omap dm timer platform device + */ +struct cap_omap_dmtimer_counter { + struct counter_device counter; + bool enabled; + /* Mutex to protect cap apply state */ + struct mutex mutex; + struct omap_dm_timer *dm_timer; + const struct omap_dm_timer_ops *pdata; + struct platform_device *dm_timer_pdev; +}; +/** + * cap_omap_dmtimer_start() - Start the cap omap dm timer in capture mode + * @omap: Pointer to cap omap dm timer counter + */ +static void cap_omap_dmtimer_start(struct cap_omap_dmtimer_counter *omap) +{ + u32 ret; + struct device *dev = &omap->dm_timer_pdev->dev; + + ret = omap->pdata->start(omap->dm_timer); + if (ret) + dev_err(dev, "%d: Failed to start timer.\n", ret); +} + +/** + * cap_omap_dmtimer_is_enabled() - Detect if the timer capture is enabled. + * @omap: Pointer to cap omap dm timer counter + * + * Return true if capture is enabled else false. + */ +static bool cap_omap_dmtimer_is_enabled(struct cap_omap_dmtimer_counter *omap) +{ + u32 status; + + status = omap->pdata->get_cap_status(omap->dm_timer); + + return !!(status & OMAP_TIMER_CTRL_ST); +} + +static int cap_omap_dmtimer_clk_get_freq(struct counter_device *counter, + struct counter_signal *signal, u64 *freq) +{ + struct cap_omap_dmtimer_counter *omap = counter_priv(counter); + struct clk *fclk; + + fclk = omap->pdata->get_fclk(omap->dm_timer); + if (!fclk) { + dev_err(counter->parent, "invalid dmtimer fclk\n"); + return -EINVAL; + } + + *freq = clk_get_rate(fclk); + if (!(*freq)) { + dev_err(counter->parent, "invalid dmtimer fclk rate\n"); + return -EINVAL; + } + + return 0; +} +/** + * cap_omap_dmtimer_apply() - Changes the state of the cap omap dm timer counter. + * @counter:Pointer to capture counter. + * + * Return 0 if successfully changed the state else appropriate error. + */ +static int cap_omap_dmtimer_apply(struct counter_device *counter) +{ + struct cap_omap_dmtimer_counter *omap = counter_priv(counter); + struct device *dev = &omap->dm_timer_pdev->dev; + int ret = 0; + + /* Ensure that the timer is in stop mode so that the configs can be changed. */ + if (cap_omap_dmtimer_is_enabled(omap)) { + ret = omap->pdata->stop(omap->dm_timer); + if (ret) + dev_err(dev, "%d: Failed to stop timer.\n", ret); + } + + ret = omap->pdata->set_cap(omap->dm_timer, true, true); + if (ret) { + dev_err(dev, "%d: Failed to set timer capture configuration.\n", ret); + return ret; + } + + cap_omap_dmtimer_start(omap); + + return ret; +} + +static int cap_omap_dmtimer_capture(struct counter_device *counter, + struct counter_count *count, u64 *duty_cycle) +{ + struct cap_omap_dmtimer_counter *omap = counter_priv(counter); + *duty_cycle = 0; + + if (!omap->enabled) { + dev_err(counter->parent, "Timer is disabled.\n"); + omap->pdata->stop(omap->dm_timer); + return 0; + } + + *duty_cycle = omap->pdata->read_cap(omap->dm_timer, false); + + *duty_cycle = *duty_cycle > 0 ? *duty_cycle : 0; + + return *duty_cycle; +} + +static int cap_omap_dmtimer_period(struct counter_device *counter, + struct counter_signal *signal, u64 *freq) +{ + struct cap_omap_dmtimer_counter *omap = counter_priv(counter); + u64 clk_freq = 0; + u64 period = 0; + *freq = 0; + + if (!omap->enabled) { + dev_err(counter->parent, "Timer is disabled.\n"); + omap->pdata->stop(omap->dm_timer); + return 0; + } + + period = omap->pdata->read_cap(omap->dm_timer, true); + cap_omap_dmtimer_clk_get_freq(counter, signal, &clk_freq); + + if (period > 0) + *freq = clk_freq/period; + + return *freq+1; +} +static int cap_omap_dmtimer_enable_read(struct counter_device *counter, + struct counter_count *count, u8 *enable) +{ + struct cap_omap_dmtimer_counter *omap = counter_priv(counter); + + *enable = omap->enabled; + + return 0; +} + +static int cap_omap_dmtimer_count_read(struct counter_device *counter, + struct counter_count *count, u64 *val) +{ + struct cap_omap_dmtimer_counter *omap = counter_priv(counter); + + *val = omap->pdata->read_counter(omap->dm_timer); + + return 0; +} + +static int cap_omap_dmtimer_count_write(struct counter_device *counter, + struct counter_count *count, u64 val) +{ + struct cap_omap_dmtimer_counter *omap = counter_priv(counter); + + if (val > U32_MAX) + return -ERANGE; + + omap->pdata->write_counter(omap->dm_timer, val); + + return 0; +} + +static int cap_omap_dmtimer_enable_write(struct counter_device *counter, + struct counter_count *count, u8 enable) +{ + struct cap_omap_dmtimer_counter *omap = counter_priv(counter); + + if (enable == omap->enabled) + goto out; + + if (enable) + cap_omap_dmtimer_apply(counter); + else + omap->pdata->stop(omap->dm_timer); + + omap->enabled = enable; +out: + return 0; +} + +static int cap_omap_dmtimer_function_read(struct counter_device *counter, + struct counter_count *count, + enum counter_function *function) +{ + *function = COUNTER_FUNCTION_INCREASE; + + return 0; +} + +static int cap_omap_dmtimer_action_read(struct counter_device *counter, + struct counter_count *count, + struct counter_synapse *synapse, + enum counter_synapse_action *action) +{ + *action = (synapse->signal->id == TIMER_CLOCK_SIG) ? + COUNTER_SYNAPSE_ACTION_RISING_EDGE : + COUNTER_SYNAPSE_ACTION_NONE; + + return 0; +} + +static const struct counter_ops cap_omap_dmtimer_ops = { + .count_read = cap_omap_dmtimer_count_read, + .count_write = cap_omap_dmtimer_count_write, + .function_read = cap_omap_dmtimer_function_read, + .action_read = cap_omap_dmtimer_action_read, +}; + +static const enum counter_function cap_omap_dmtimer_functions[] = { + COUNTER_FUNCTION_INCREASE, +}; + +static struct counter_comp cap_omap_dmtimer_clock_ext[] = { + COUNTER_COMP_SIGNAL_U64("frequency", cap_omap_dmtimer_clk_get_freq, NULL), +}; + +static struct counter_signal cap_omap_dmtimer_signals[] = { + { + .id = TIMER_CLOCK_SIG, + .name = "Clock Signal", + .ext = cap_omap_dmtimer_clock_ext, + .num_ext = ARRAY_SIZE(cap_omap_dmtimer_clock_ext), + }, + { + .id = TIMER_INPUT_SIG, + .name = "Input Signal", + }, +}; + +/* Counter will increase at rising edges of a clock */ +static const enum counter_synapse_action cap_omap_dmtimer_clock_actions[] = { + COUNTER_SYNAPSE_ACTION_RISING_EDGE, +}; + +/* No trigger here */ +static const enum counter_synapse_action cap_omap_dmtimer_input_actions[] = { + COUNTER_SYNAPSE_ACTION_NONE, +}; + +static struct counter_synapse cap_omap_dmtimer_synapses[] = { + { + .actions_list = cap_omap_dmtimer_clock_actions, + .num_actions = ARRAY_SIZE(cap_omap_dmtimer_clock_actions), + .signal = &cap_omap_dmtimer_signals[TIMER_CLOCK_SIG], + }, + { + .actions_list = cap_omap_dmtimer_input_actions, + .num_actions = ARRAY_SIZE(cap_omap_dmtimer_input_actions), + .signal = &cap_omap_dmtimer_signals[TIMER_INPUT_SIG], + }, +}; + +static struct counter_comp cap_omap_dmtimer_count_ext[] = { + COUNTER_COMP_CAPTURE(cap_omap_dmtimer_capture, NULL), + COUNTER_COMP_ENABLE(cap_omap_dmtimer_enable_read, cap_omap_dmtimer_enable_write), + COUNTER_COMP_FREQUENCY(cap_omap_dmtimer_period), +}; + +static struct counter_count cap_omap_dmtimer_counts[] = { + { + .name = "Timestamp Counter", + .functions_list = cap_omap_dmtimer_functions, + .num_functions = ARRAY_SIZE(cap_omap_dmtimer_functions), + .synapses = cap_omap_dmtimer_synapses, + .num_synapses = ARRAY_SIZE(cap_omap_dmtimer_synapses), + .ext = cap_omap_dmtimer_count_ext, + .num_ext = ARRAY_SIZE(cap_omap_dmtimer_count_ext), + }, +}; + +static int cap_omap_dmtimer_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct dmtimer_platform_data *timer_pdata; + const struct omap_dm_timer_ops *pdata; + struct platform_device *timer_pdev; + struct omap_dm_timer *dm_timer; + struct device_node *timer; + struct cap_omap_dmtimer_counter *omap; + struct counter_device *counter_dev; + int ret = 0; + + timer = of_parse_phandle(np, "ti,timers", 0); + if (!timer) { + dev_err(&pdev->dev, "Unable to find Timer node\n"); + return -ENODEV; + } + + timer_pdev = of_find_device_by_node(timer); + if (!timer_pdev) { + dev_err(&pdev->dev, "Unable to find Timer pdev\n"); + ret = -ENODEV; + goto err_find_timer_pdev; + } + timer_pdata = dev_get_platdata(&timer_pdev->dev); + if (!timer_pdata) { + dev_dbg(&pdev->dev, + "dmtimer pdata structure NULL, deferring probe\n"); + ret = -EPROBE_DEFER; + dev_err_probe(&pdev->dev, ret, "Probe deferred\n"); + goto err_platdata; + } + + pdata = timer_pdata->timer_ops; + + if (!pdata || !pdata->request_by_node || + !pdata->free || + !pdata->enable || + !pdata->disable || + !pdata->get_fclk || + !pdata->start || + !pdata->stop || + !pdata->set_load || + !pdata->set_match || + !pdata->set_cap || + !pdata->get_cap_status || + !pdata->read_cap || + !pdata->set_prescaler || + !pdata->write_counter) { + dev_err(&pdev->dev, "Incomplete dmtimer pdata structure\n"); + ret = -EINVAL; + goto err_platdata; + } + + dm_timer = pdata->request_by_node(timer); + if (!dm_timer) { + ret = -EPROBE_DEFER; + goto err_request_timer; + } + + /* struct cap_omap_dmtimer_counter *omap */ + counter_dev = devm_counter_alloc(dev, sizeof(*omap)); + if (!counter_dev) { + dev_err(&pdev->dev, "Unable to allocate dmtimercounter\n"); + ret = -ENOMEM; + goto err_alloc_omap; + } + omap = counter_priv(counter_dev); + + counter_dev->name = TIMER_DRV_NAME; + counter_dev->parent = dev; + counter_dev->ops = &cap_omap_dmtimer_ops; + counter_dev->signals = cap_omap_dmtimer_signals; + counter_dev->num_signals = ARRAY_SIZE(cap_omap_dmtimer_signals); + counter_dev->counts = cap_omap_dmtimer_counts; + counter_dev->num_counts = ARRAY_SIZE(cap_omap_dmtimer_counts); + mutex_init(&omap->mutex); + omap->pdata = pdata; + omap->dm_timer = dm_timer; + omap->dm_timer_pdev = timer_pdev; + + if (pm_runtime_active(&omap->dm_timer_pdev->dev)) + omap->pdata->stop(omap->dm_timer); + + of_node_put(timer); + + platform_set_drvdata(pdev, counter_dev); + + ret = devm_counter_add(dev, counter_dev); + if (ret) + return dev_err_probe(dev, ret, "failed to add counter\n"); + + return 0; + +err_alloc_omap: + pdata->free(dm_timer); +err_request_timer: + +err_platdata: + put_device(&timer_pdev->dev); +err_find_timer_pdev: + + of_node_put(timer); + + return ret; +} + +static void cap_omap_dmtimer_remove(struct platform_device *pdev) +{ + struct counter_device *counter = platform_get_drvdata(pdev); + struct cap_omap_dmtimer_counter *omap = counter_priv(counter); + + counter_unregister(counter); + + if (pm_runtime_active(&omap->dm_timer_pdev->dev)) + omap->pdata->stop(omap->dm_timer); + + omap->pdata->free(omap->dm_timer); + + put_device(&omap->dm_timer_pdev->dev); + + mutex_destroy(&omap->mutex); + +} + +static const struct of_device_id cap_omap_dmtimer_of_match[] = { + {.compatible = "ti,omap-dmtimer-cap"}, + {} +}; +MODULE_DEVICE_TABLE(of, cap_omap_dmtimer_of_match); + +static struct platform_driver cap_omap_dmtimer_driver = { + .driver = { + .name = "omap-dmtimer-cap", + .of_match_table = cap_omap_dmtimer_of_match, + }, + .probe = cap_omap_dmtimer_probe, + .remove = cap_omap_dmtimer_remove, +}; +module_platform_driver(cap_omap_dmtimer_driver); + +MODULE_AUTHOR("Gokul Praveen <g-praveen@ti.com>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("OMAP CAP Driver using Dual-mode Timers"); +MODULE_IMPORT_NS("COUNTER"); -- 2.34.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] counter: ti-dmtimer-cap : capture driver support for OMAP DM timer 2025-09-09 8:00 ` [PATCH 2/2] counter: ti-dmtimer-cap : capture driver support for OMAP DM timer Gokul Praveen @ 2025-09-09 14:58 ` Andrew Davis 2025-09-10 6:39 ` kernel test robot 1 sibling, 0 replies; 12+ messages in thread From: Andrew Davis @ 2025-09-09 14:58 UTC (permalink / raw) To: Gokul Praveen, j-keerthy, vigneshr, wbg, linux-kernel, robh, krzk+dt, conor+dt, devicetree Cc: u-kumar1, n-francis On 9/9/25 3:00 AM, Gokul Praveen wrote: > Enable capture driver support for OMAP DM timer hardware. > > DM timer hardware supports capture feature.It can be used > to timestamp events (falling/rising edges) detected on input signal. > > The timer IO pin can also be configured in PWM mode but this > driver supports simple independent capture functionality. > > It is assumed that the capture signal is active else both duty cycle > and period returned by driver will not be valid. > > Signed-off-by: Gokul Praveen <g-praveen@ti.com> > --- > BOOT LOGS: > https://gist.github.com/GokulPraveen2001/581fa07b2e93f30dea9f6188a97b944b > > TIMER CAPTURE DTSO: > > &{/} { > > main_cap10: dmtimer-main-cap-10 { > compatible = "ti,omap-dmtimer-cap"; > ti,timers = <&main_timer10>; > pinctrl-0 = <&maindmtimer1_pins_default>,<&main_timer10_ctrl_config>; > pinctrl-names = "default"; > }; > > }; > > &main_timer10{ > status = "okay"; > }; > > /*MAIN_TIMERIO1*/ > &main_pmx0 { > maindmtimer1_pins_default: maindmtimer1-default-pins { > pinctrl-single,pins = < > J784S4_IOPAD(0x0ec, PIN_INPUT, 0) /* (AN37) TIMER_IO1:Input mode for Capture*/ > >; > }; > > }; > > /*Sets in CAP mode using MAIN TIMER IOX(X=1 here) CTRL MMR REGISTERS*/ > &main_timerio_input { > main_timer10_ctrl_config: main-timer10-ctrl-config { > pinctrl-single,pins = < > J784S4_IOPAD(0x28,0,0x1)>; /* MAIN_TIMER_10 will use MAIN_TIMERIO1 pin(maindmtimer1-default-pins) for capture*/ > }; > }; > --- > drivers/counter/Kconfig | 13 + > drivers/counter/Makefile | 1 + > drivers/counter/ti-dmtimer-cap.c | 455 +++++++++++++++++++++++++++++++ > 3 files changed, 469 insertions(+) > create mode 100644 drivers/counter/ti-dmtimer-cap.c > > diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig > index d30d22dfe577..bec07cf15779 100644 > --- a/drivers/counter/Kconfig > +++ b/drivers/counter/Kconfig > @@ -121,6 +121,19 @@ config STM32_TIMER_CNT > To compile this driver as a module, choose M here: the > module will be called stm32-timer-cnt. > > +config TI_DMTIMER_CAPTURE > + tristate "OMAP Dual-Mode Timer Capture support" > + depends on OMAP_DM_TIMER || COMPILE_TEST > + help > + Select this option to use the Texas Instruments OMAP DM Timer > + driver in capture mode. > + > + It can be used to timestamp events (falling/rising edges) detected > + on Timer input signal. > + > + To compile this driver as a module, choose M here: the module > + will be called ti-dmtimer-cap. > + > config TI_ECAP_CAPTURE > tristate "TI eCAP capture driver" > depends on ARCH_OMAP2PLUS || ARCH_DAVINCI_DA8XX || ARCH_KEYSTONE || ARCH_K3 || COMPILE_TEST > diff --git a/drivers/counter/Makefile b/drivers/counter/Makefile > index fa3c1d08f706..7c2d226fe984 100644 > --- a/drivers/counter/Makefile > +++ b/drivers/counter/Makefile > @@ -17,3 +17,4 @@ 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 > +obj-$(CONFIG_TI_DMTIMER_CAPTURE) +=ti-dmtimer-cap.o > diff --git a/drivers/counter/ti-dmtimer-cap.c b/drivers/counter/ti-dmtimer-cap.c > new file mode 100644 > index 000000000000..dedfb15faa10 > --- /dev/null > +++ b/drivers/counter/ti-dmtimer-cap.c > @@ -0,0 +1,455 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * DM timer Capture Driver Add proper copyright. > + */ > + > +#include <clocksource/timer-ti-dm.h> > +#include <linux/atomic.h> > +#include <linux/counter.h> > +#include <linux/clk.h> > +#include <linux/err.h> > +#include <linux/interrupt.h> > +#include <linux/io.h> > +#include <linux/kernel.h> > +#include <linux/module.h> > +#include <linux/mod_devicetable.h> > +#include <linux/mutex.h> > +#include <linux/of.h> > +#include <linux/of_platform.h> > +#include <linux/platform_data/dmtimer-omap.h> > +#include <linux/platform_device.h> > +#include <linux/pm_runtime.h> > +#include <linux/slab.h> > +#include <linux/time.h> > + > +#define TIMER_DRV_NAME "CAP_OMAP_DMTIMER" > +/* Timer signals */ > +#define TIMER_CLOCK_SIG 0 > +#define TIMER_INPUT_SIG 1 > + > +/** > + * struct cap_omap_dmtimer_counter - Structure representing a cap counter > + * corresponding to omap dm timer. > + * @counter: Capture counter > + * @enabled: Tracks the enable status of omap dm timer. > + * @mutex: Mutex to protect cap apply state > + * @dm_timer: Pointer to omap dm timer. > + * @pdata: Pointer to omap dm timer ops. > + * @dm_timer_pdev: Pointer to omap dm timer platform device > + */ > +struct cap_omap_dmtimer_counter { > + struct counter_device counter; > + bool enabled; > + /* Mutex to protect cap apply state */ > + struct mutex mutex; > + struct omap_dm_timer *dm_timer; > + const struct omap_dm_timer_ops *pdata; > + struct platform_device *dm_timer_pdev; > +}; Random missing newlines everywhere. > +/** > + * cap_omap_dmtimer_start() - Start the cap omap dm timer in capture mode > + * @omap: Pointer to cap omap dm timer counter > + */ > +static void cap_omap_dmtimer_start(struct cap_omap_dmtimer_counter *omap) > +{ > + u32 ret; > + struct device *dev = &omap->dm_timer_pdev->dev; > + > + ret = omap->pdata->start(omap->dm_timer); > + if (ret) > + dev_err(dev, "%d: Failed to start timer.\n", ret); > +} > + > +/** > + * cap_omap_dmtimer_is_enabled() - Detect if the timer capture is enabled. > + * @omap: Pointer to cap omap dm timer counter > + * > + * Return true if capture is enabled else false. > + */ > +static bool cap_omap_dmtimer_is_enabled(struct cap_omap_dmtimer_counter *omap) > +{ > + u32 status; > + > + status = omap->pdata->get_cap_status(omap->dm_timer); > + > + return !!(status & OMAP_TIMER_CTRL_ST); > +} > + > +static int cap_omap_dmtimer_clk_get_freq(struct counter_device *counter, > + struct counter_signal *signal, u64 *freq) > +{ > + struct cap_omap_dmtimer_counter *omap = counter_priv(counter); > + struct clk *fclk; > + > + fclk = omap->pdata->get_fclk(omap->dm_timer); > + if (!fclk) { > + dev_err(counter->parent, "invalid dmtimer fclk\n"); > + return -EINVAL; > + } > + > + *freq = clk_get_rate(fclk); > + if (!(*freq)) { > + dev_err(counter->parent, "invalid dmtimer fclk rate\n"); > + return -EINVAL; > + } > + > + return 0; > +} > +/** > + * cap_omap_dmtimer_apply() - Changes the state of the cap omap dm timer counter. > + * @counter:Pointer to capture counter. > + * > + * Return 0 if successfully changed the state else appropriate error. > + */ > +static int cap_omap_dmtimer_apply(struct counter_device *counter) > +{ > + struct cap_omap_dmtimer_counter *omap = counter_priv(counter); > + struct device *dev = &omap->dm_timer_pdev->dev; > + int ret = 0; > + > + /* Ensure that the timer is in stop mode so that the configs can be changed. */ > + if (cap_omap_dmtimer_is_enabled(omap)) { > + ret = omap->pdata->stop(omap->dm_timer); > + if (ret) > + dev_err(dev, "%d: Failed to stop timer.\n", ret); > + } > + > + ret = omap->pdata->set_cap(omap->dm_timer, true, true); > + if (ret) { > + dev_err(dev, "%d: Failed to set timer capture configuration.\n", ret); > + return ret; > + } > + > + cap_omap_dmtimer_start(omap); > + > + return ret; > +} > + > +static int cap_omap_dmtimer_capture(struct counter_device *counter, > + struct counter_count *count, u64 *duty_cycle) > +{ > + struct cap_omap_dmtimer_counter *omap = counter_priv(counter); > + *duty_cycle = 0; > + > + if (!omap->enabled) { > + dev_err(counter->parent, "Timer is disabled.\n"); > + omap->pdata->stop(omap->dm_timer); > + return 0; > + } > + > + *duty_cycle = omap->pdata->read_cap(omap->dm_timer, false); > + > + *duty_cycle = *duty_cycle > 0 ? *duty_cycle : 0; > + > + return *duty_cycle; > +} > + > +static int cap_omap_dmtimer_period(struct counter_device *counter, > + struct counter_signal *signal, u64 *freq) > +{ > + struct cap_omap_dmtimer_counter *omap = counter_priv(counter); > + u64 clk_freq = 0; > + u64 period = 0; > + *freq = 0; > + > + if (!omap->enabled) { > + dev_err(counter->parent, "Timer is disabled.\n"); > + omap->pdata->stop(omap->dm_timer); > + return 0; > + } > + > + period = omap->pdata->read_cap(omap->dm_timer, true); > + cap_omap_dmtimer_clk_get_freq(counter, signal, &clk_freq); > + > + if (period > 0) > + *freq = clk_freq/period; > + > + return *freq+1; > +} > +static int cap_omap_dmtimer_enable_read(struct counter_device *counter, > + struct counter_count *count, u8 *enable) > +{ > + struct cap_omap_dmtimer_counter *omap = counter_priv(counter); > + > + *enable = omap->enabled; > + > + return 0; > +} > + > +static int cap_omap_dmtimer_count_read(struct counter_device *counter, > + struct counter_count *count, u64 *val) > +{ > + struct cap_omap_dmtimer_counter *omap = counter_priv(counter); > + > + *val = omap->pdata->read_counter(omap->dm_timer); > + > + return 0; > +} > + > +static int cap_omap_dmtimer_count_write(struct counter_device *counter, > + struct counter_count *count, u64 val) > +{ > + struct cap_omap_dmtimer_counter *omap = counter_priv(counter); > + > + if (val > U32_MAX) > + return -ERANGE; > + > + omap->pdata->write_counter(omap->dm_timer, val); > + > + return 0; > +} > + > +static int cap_omap_dmtimer_enable_write(struct counter_device *counter, > + struct counter_count *count, u8 enable) > +{ > + struct cap_omap_dmtimer_counter *omap = counter_priv(counter); > + > + if (enable == omap->enabled) > + goto out; Return 0. Seems very odd code style quirks like this and well everywhere in this patch.. > + > + if (enable) > + cap_omap_dmtimer_apply(counter); > + else > + omap->pdata->stop(omap->dm_timer); > + > + omap->enabled = enable; > +out: > + return 0; > +} > + > +static int cap_omap_dmtimer_function_read(struct counter_device *counter, > + struct counter_count *count, > + enum counter_function *function) > +{ > + *function = COUNTER_FUNCTION_INCREASE; > + > + return 0; > +} > + > +static int cap_omap_dmtimer_action_read(struct counter_device *counter, > + struct counter_count *count, > + struct counter_synapse *synapse, > + enum counter_synapse_action *action) > +{ > + *action = (synapse->signal->id == TIMER_CLOCK_SIG) ? > + COUNTER_SYNAPSE_ACTION_RISING_EDGE : > + COUNTER_SYNAPSE_ACTION_NONE; > + > + return 0; > +} > + > +static const struct counter_ops cap_omap_dmtimer_ops = { > + .count_read = cap_omap_dmtimer_count_read, > + .count_write = cap_omap_dmtimer_count_write, > + .function_read = cap_omap_dmtimer_function_read, > + .action_read = cap_omap_dmtimer_action_read, > +}; > + > +static const enum counter_function cap_omap_dmtimer_functions[] = { > + COUNTER_FUNCTION_INCREASE, > +}; > + > +static struct counter_comp cap_omap_dmtimer_clock_ext[] = { > + COUNTER_COMP_SIGNAL_U64("frequency", cap_omap_dmtimer_clk_get_freq, NULL), > +}; > + > +static struct counter_signal cap_omap_dmtimer_signals[] = { > + { > + .id = TIMER_CLOCK_SIG, > + .name = "Clock Signal", > + .ext = cap_omap_dmtimer_clock_ext, > + .num_ext = ARRAY_SIZE(cap_omap_dmtimer_clock_ext), > + }, > + { > + .id = TIMER_INPUT_SIG, > + .name = "Input Signal", > + }, > +}; > + > +/* Counter will increase at rising edges of a clock */ > +static const enum counter_synapse_action cap_omap_dmtimer_clock_actions[] = { > + COUNTER_SYNAPSE_ACTION_RISING_EDGE, > +}; > + > +/* No trigger here */ > +static const enum counter_synapse_action cap_omap_dmtimer_input_actions[] = { > + COUNTER_SYNAPSE_ACTION_NONE, > +}; > + > +static struct counter_synapse cap_omap_dmtimer_synapses[] = { > + { > + .actions_list = cap_omap_dmtimer_clock_actions, > + .num_actions = ARRAY_SIZE(cap_omap_dmtimer_clock_actions), > + .signal = &cap_omap_dmtimer_signals[TIMER_CLOCK_SIG], > + }, > + { > + .actions_list = cap_omap_dmtimer_input_actions, > + .num_actions = ARRAY_SIZE(cap_omap_dmtimer_input_actions), > + .signal = &cap_omap_dmtimer_signals[TIMER_INPUT_SIG], > + }, > +}; > + > +static struct counter_comp cap_omap_dmtimer_count_ext[] = { > + COUNTER_COMP_CAPTURE(cap_omap_dmtimer_capture, NULL), > + COUNTER_COMP_ENABLE(cap_omap_dmtimer_enable_read, cap_omap_dmtimer_enable_write), > + COUNTER_COMP_FREQUENCY(cap_omap_dmtimer_period), > +}; > + > +static struct counter_count cap_omap_dmtimer_counts[] = { > + { > + .name = "Timestamp Counter", > + .functions_list = cap_omap_dmtimer_functions, > + .num_functions = ARRAY_SIZE(cap_omap_dmtimer_functions), > + .synapses = cap_omap_dmtimer_synapses, > + .num_synapses = ARRAY_SIZE(cap_omap_dmtimer_synapses), > + .ext = cap_omap_dmtimer_count_ext, > + .num_ext = ARRAY_SIZE(cap_omap_dmtimer_count_ext), > + }, > +}; > + > +static int cap_omap_dmtimer_probe(struct platform_device *pdev) > +{ > + struct device_node *np = pdev->dev.of_node; > + struct device *dev = &pdev->dev; > + struct dmtimer_platform_data *timer_pdata; > + const struct omap_dm_timer_ops *pdata; > + struct platform_device *timer_pdev; > + struct omap_dm_timer *dm_timer; > + struct device_node *timer; > + struct cap_omap_dmtimer_counter *omap; > + struct counter_device *counter_dev; > + int ret = 0; > + > + timer = of_parse_phandle(np, "ti,timers", 0); > + if (!timer) { > + dev_err(&pdev->dev, "Unable to find Timer node\n"); > + return -ENODEV; > + } > + > + timer_pdev = of_find_device_by_node(timer); > + if (!timer_pdev) { > + dev_err(&pdev->dev, "Unable to find Timer pdev\n"); > + ret = -ENODEV; > + goto err_find_timer_pdev; > + } > + timer_pdata = dev_get_platdata(&timer_pdev->dev); > + if (!timer_pdata) { > + dev_dbg(&pdev->dev, > + "dmtimer pdata structure NULL, deferring probe\n"); > + ret = -EPROBE_DEFER; > + dev_err_probe(&pdev->dev, ret, "Probe deferred\n"); > + goto err_platdata; > + } > + > + pdata = timer_pdata->timer_ops; > + > + if (!pdata || !pdata->request_by_node || > + !pdata->free || > + !pdata->enable || > + !pdata->disable || > + !pdata->get_fclk || > + !pdata->start || > + !pdata->stop || > + !pdata->set_load || > + !pdata->set_match || > + !pdata->set_cap || > + !pdata->get_cap_status || > + !pdata->read_cap || tab vs space issues in several spots, fix your editor. > + !pdata->set_prescaler || > + !pdata->write_counter) { > + dev_err(&pdev->dev, "Incomplete dmtimer pdata structure\n"); > + ret = -EINVAL; > + goto err_platdata; > + } > + > + dm_timer = pdata->request_by_node(timer); > + if (!dm_timer) { > + ret = -EPROBE_DEFER; > + goto err_request_timer; > + } > + > + /* struct cap_omap_dmtimer_counter *omap */ > + counter_dev = devm_counter_alloc(dev, sizeof(*omap)); > + if (!counter_dev) { > + dev_err(&pdev->dev, "Unable to allocate dmtimercounter\n"); > + ret = -ENOMEM; > + goto err_alloc_omap; > + } > + omap = counter_priv(counter_dev); > + > + counter_dev->name = TIMER_DRV_NAME; > + counter_dev->parent = dev; > + counter_dev->ops = &cap_omap_dmtimer_ops; > + counter_dev->signals = cap_omap_dmtimer_signals; > + counter_dev->num_signals = ARRAY_SIZE(cap_omap_dmtimer_signals); > + counter_dev->counts = cap_omap_dmtimer_counts; > + counter_dev->num_counts = ARRAY_SIZE(cap_omap_dmtimer_counts); > + mutex_init(&omap->mutex); > + omap->pdata = pdata; > + omap->dm_timer = dm_timer; > + omap->dm_timer_pdev = timer_pdev; > + > + if (pm_runtime_active(&omap->dm_timer_pdev->dev)) > + omap->pdata->stop(omap->dm_timer); > + > + of_node_put(timer); Why free down here, move this up right after its last use. > + > + platform_set_drvdata(pdev, counter_dev); > + > + ret = devm_counter_add(dev, counter_dev); > + if (ret) > + return dev_err_probe(dev, ret, "failed to add counter\n"); > + > + return 0; > + > +err_alloc_omap: > + pdata->free(dm_timer); > +err_request_timer: > + Unused label? Andrew > +err_platdata: > + put_device(&timer_pdev->dev); > +err_find_timer_pdev: > + > + of_node_put(timer); > + > + return ret; > +} > + > +static void cap_omap_dmtimer_remove(struct platform_device *pdev) > +{ > + struct counter_device *counter = platform_get_drvdata(pdev); > + struct cap_omap_dmtimer_counter *omap = counter_priv(counter); > + > + counter_unregister(counter); > + > + if (pm_runtime_active(&omap->dm_timer_pdev->dev)) > + omap->pdata->stop(omap->dm_timer); > + > + omap->pdata->free(omap->dm_timer); > + > + put_device(&omap->dm_timer_pdev->dev); > + > + mutex_destroy(&omap->mutex); > + > +} > + > +static const struct of_device_id cap_omap_dmtimer_of_match[] = { > + {.compatible = "ti,omap-dmtimer-cap"}, > + {} > +}; > +MODULE_DEVICE_TABLE(of, cap_omap_dmtimer_of_match); > + > +static struct platform_driver cap_omap_dmtimer_driver = { > + .driver = { > + .name = "omap-dmtimer-cap", > + .of_match_table = cap_omap_dmtimer_of_match, > + }, > + .probe = cap_omap_dmtimer_probe, > + .remove = cap_omap_dmtimer_remove, > +}; > +module_platform_driver(cap_omap_dmtimer_driver); > + > +MODULE_AUTHOR("Gokul Praveen <g-praveen@ti.com>"); > +MODULE_LICENSE("GPL"); > +MODULE_DESCRIPTION("OMAP CAP Driver using Dual-mode Timers"); > +MODULE_IMPORT_NS("COUNTER"); ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] counter: ti-dmtimer-cap : capture driver support for OMAP DM timer 2025-09-09 8:00 ` [PATCH 2/2] counter: ti-dmtimer-cap : capture driver support for OMAP DM timer Gokul Praveen 2025-09-09 14:58 ` Andrew Davis @ 2025-09-10 6:39 ` kernel test robot 1 sibling, 0 replies; 12+ messages in thread From: kernel test robot @ 2025-09-10 6:39 UTC (permalink / raw) To: Gokul Praveen, j-keerthy, vigneshr, wbg, linux-kernel, robh, krzk+dt, conor+dt, devicetree Cc: oe-kbuild-all, g-praveen, u-kumar1, n-francis Hi Gokul, kernel test robot noticed the following build errors: [auto build test ERROR on robh/for-next] [also build test ERROR on linus/master v6.17-rc5 next-20250909] [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/Gokul-Praveen/dt-bindings-counter-Add-new-ti-omap-dmtimer-cap-compatible/20250909-160651 base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next patch link: https://lore.kernel.org/r/20250909080042.36127-3-g-praveen%40ti.com patch subject: [PATCH 2/2] counter: ti-dmtimer-cap : capture driver support for OMAP DM timer config: m68k-allyesconfig (https://download.01.org/0day-ci/archive/20250910/202509101412.ze6xyOUu-lkp@intel.com/config) compiler: m68k-linux-gcc (GCC) 15.1.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250910/202509101412.ze6xyOUu-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202509101412.ze6xyOUu-lkp@intel.com/ All errors (new ones prefixed by >>): drivers/counter/ti-dmtimer-cap.c: In function 'cap_omap_dmtimer_is_enabled': >> drivers/counter/ti-dmtimer-cap.c:73:31: error: 'const struct omap_dm_timer_ops' has no member named 'get_cap_status'; did you mean 'get_pwm_status'? 73 | status = omap->pdata->get_cap_status(omap->dm_timer); | ^~~~~~~~~~~~~~ | get_pwm_status drivers/counter/ti-dmtimer-cap.c: In function 'cap_omap_dmtimer_apply': >> drivers/counter/ti-dmtimer-cap.c:117:26: error: 'const struct omap_dm_timer_ops' has no member named 'set_cap' 117 | ret = omap->pdata->set_cap(omap->dm_timer, true, true); | ^~ drivers/counter/ti-dmtimer-cap.c: In function 'cap_omap_dmtimer_capture': >> drivers/counter/ti-dmtimer-cap.c:140:34: error: 'const struct omap_dm_timer_ops' has no member named 'read_cap' 140 | *duty_cycle = omap->pdata->read_cap(omap->dm_timer, false); | ^~ drivers/counter/ti-dmtimer-cap.c: In function 'cap_omap_dmtimer_period': drivers/counter/ti-dmtimer-cap.c:161:29: error: 'const struct omap_dm_timer_ops' has no member named 'read_cap' 161 | period = omap->pdata->read_cap(omap->dm_timer, true); | ^~ drivers/counter/ti-dmtimer-cap.c: In function 'cap_omap_dmtimer_probe': drivers/counter/ti-dmtimer-cap.c:355:19: error: 'const struct omap_dm_timer_ops' has no member named 'set_cap' 355 | !pdata->set_cap || | ^~ drivers/counter/ti-dmtimer-cap.c:356:21: error: 'const struct omap_dm_timer_ops' has no member named 'get_cap_status'; did you mean 'get_pwm_status'? 356 | !pdata->get_cap_status || | ^~~~~~~~~~~~~~ | get_pwm_status drivers/counter/ti-dmtimer-cap.c:357:23: error: 'const struct omap_dm_timer_ops' has no member named 'read_cap' 357 | !pdata->read_cap || | ^~ vim +73 drivers/counter/ti-dmtimer-cap.c 62 63 /** 64 * cap_omap_dmtimer_is_enabled() - Detect if the timer capture is enabled. 65 * @omap: Pointer to cap omap dm timer counter 66 * 67 * Return true if capture is enabled else false. 68 */ 69 static bool cap_omap_dmtimer_is_enabled(struct cap_omap_dmtimer_counter *omap) 70 { 71 u32 status; 72 > 73 status = omap->pdata->get_cap_status(omap->dm_timer); 74 75 return !!(status & OMAP_TIMER_CTRL_ST); 76 } 77 78 static int cap_omap_dmtimer_clk_get_freq(struct counter_device *counter, 79 struct counter_signal *signal, u64 *freq) 80 { 81 struct cap_omap_dmtimer_counter *omap = counter_priv(counter); 82 struct clk *fclk; 83 84 fclk = omap->pdata->get_fclk(omap->dm_timer); 85 if (!fclk) { 86 dev_err(counter->parent, "invalid dmtimer fclk\n"); 87 return -EINVAL; 88 } 89 90 *freq = clk_get_rate(fclk); 91 if (!(*freq)) { 92 dev_err(counter->parent, "invalid dmtimer fclk rate\n"); 93 return -EINVAL; 94 } 95 96 return 0; 97 } 98 /** 99 * cap_omap_dmtimer_apply() - Changes the state of the cap omap dm timer counter. 100 * @counter:Pointer to capture counter. 101 * 102 * Return 0 if successfully changed the state else appropriate error. 103 */ 104 static int cap_omap_dmtimer_apply(struct counter_device *counter) 105 { 106 struct cap_omap_dmtimer_counter *omap = counter_priv(counter); 107 struct device *dev = &omap->dm_timer_pdev->dev; 108 int ret = 0; 109 110 /* Ensure that the timer is in stop mode so that the configs can be changed. */ 111 if (cap_omap_dmtimer_is_enabled(omap)) { 112 ret = omap->pdata->stop(omap->dm_timer); 113 if (ret) 114 dev_err(dev, "%d: Failed to stop timer.\n", ret); 115 } 116 > 117 ret = omap->pdata->set_cap(omap->dm_timer, true, true); 118 if (ret) { 119 dev_err(dev, "%d: Failed to set timer capture configuration.\n", ret); 120 return ret; 121 } 122 123 cap_omap_dmtimer_start(omap); 124 125 return ret; 126 } 127 128 static int cap_omap_dmtimer_capture(struct counter_device *counter, 129 struct counter_count *count, u64 *duty_cycle) 130 { 131 struct cap_omap_dmtimer_counter *omap = counter_priv(counter); 132 *duty_cycle = 0; 133 134 if (!omap->enabled) { 135 dev_err(counter->parent, "Timer is disabled.\n"); 136 omap->pdata->stop(omap->dm_timer); 137 return 0; 138 } 139 > 140 *duty_cycle = omap->pdata->read_cap(omap->dm_timer, false); 141 142 *duty_cycle = *duty_cycle > 0 ? *duty_cycle : 0; 143 144 return *duty_cycle; 145 } 146 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2025-10-07 14:32 UTC | newest] Thread overview: 12+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-09-09 8:00 [PATCH 0/2] Capture driver support for OMAP DM timer Gokul Praveen 2025-09-09 8:00 ` [PATCH 1/2] dt-bindings: counter: Add new ti,omap-dmtimer-cap compatible Gokul Praveen 2025-09-10 7:08 ` Krzysztof Kozlowski 2025-09-26 9:06 ` Gokul Praveen 2025-10-07 6:35 ` Krzysztof Kozlowski 2025-10-07 9:23 ` Gokul Praveen 2025-10-07 9:39 ` Krzysztof Kozlowski 2025-10-07 9:49 ` Gokul Praveen 2025-10-07 14:32 ` Krzysztof Kozlowski 2025-09-09 8:00 ` [PATCH 2/2] counter: ti-dmtimer-cap : capture driver support for OMAP DM timer Gokul Praveen 2025-09-09 14:58 ` Andrew Davis 2025-09-10 6:39 ` kernel test robot
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).