linux-iio.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [Q] Frequency & duty cycle measurement?
@ 2025-01-21 15:19 Csókás Bence
  2025-01-21 17:45 ` David Lechner
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Csókás Bence @ 2025-01-21 15:19 UTC (permalink / raw)
  To: linux-iio, linux-kernel@vger.kernel.org, linux-arm-kernel,
	timestamp
  Cc: William Breathitt Gray, Jonathan Cameron, Lars-Peter Clausen,
	Daniel Lezcano, Thomas Gleixner, Dipen Patel

Hi all,

we want to measure the frequency and duty cycle of a signal (relating to 
power consumption) using a hardware timer in our SoC (Microchip 
SAMA5D2). The hardware is capable of taking a snapshot of the timer 
value into another dedicated register pair (RA, RB) on the 
rising/falling edges, and a small `devmem`-based userspace utility was 
created as a working PoC. Now we want to move to a "proper" kernelspace 
solution.

However, none of the existing drivers seem to be able to do this; the 
closest was `drivers/counter/microchip-tcb-capture.c`, but that only 
seems to count one type of edge (rising/falling), and cannot give us the 
time between them, which would be needed for duty cycle calculation. The 
only other driver I could find was 
`drivers/clocksource/timer-atmel-tcb.c`, which again seems incapable of 
such measurements. Therefore, a new module will probably be needed; the 
question then becomes: which API to implement.

As `microchip-tcb-capture.c` uses the Generic Counter Interface, that 
was obviously a first stop. However, from what I could see, you can only 
represent (1) the number of times an edge has been encountered, and (2) 
rotary encodings (quadrature and direction-step decoders); and not the 
time between edges.

IIO_ALTVOLTAGE and IIO_CHAN_INFO_FREQUENCY/_PHASE also seemed promising 
(although the lack of IIO_CHAN_INFO_DUTY_CYCLE already posed a problem), 
until I saw that all current drivers are frequency *generators*, and not 
measurers, the latter seems to be completely unimplemented.

The only other contender I could find was the Hardware Timestamping 
Engine (HTE), but again, it's not clear whether (1) the API is even 
capable of relaying duty cycle information to userspace and (2) if it 
is, how would one go about implementing it.

It is also entirely possible I missed a driver or API that could handle 
this better, if so, please don't keep it to yourselves.

So, how could one go about implementing such a driver?

Bence


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Q] Frequency & duty cycle measurement?
  2025-01-21 15:19 [Q] Frequency & duty cycle measurement? Csókás Bence
@ 2025-01-21 17:45 ` David Lechner
  2025-01-27 15:00 ` William Breathitt Gray
  2025-02-19 22:32 ` Dipen Patel
  2 siblings, 0 replies; 9+ messages in thread
From: David Lechner @ 2025-01-21 17:45 UTC (permalink / raw)
  To: Csókás Bence, linux-iio, linux-kernel@vger.kernel.org,
	linux-arm-kernel, timestamp
  Cc: William Breathitt Gray, Jonathan Cameron, Lars-Peter Clausen,
	Daniel Lezcano, Thomas Gleixner, Dipen Patel

On 1/21/25 9:19 AM, Csókás Bence wrote:
> Hi all,
> 
> we want to measure the frequency and duty cycle of a signal (relating to power consumption) using a hardware timer in our SoC (Microchip SAMA5D2). The hardware is capable of taking a snapshot of the timer value into another dedicated register pair (RA, RB) on the rising/falling edges, and a small `devmem`-based userspace utility was created as a working PoC. Now we want to move to a "proper" kernelspace solution.
> 
> However, none of the existing drivers seem to be able to do this; the closest was `drivers/counter/microchip-tcb-capture.c`, but that only seems to count one type of edge (rising/falling), and cannot give us the time between them, which would be needed for duty cycle calculation. The only other driver I could find was `drivers/clocksource/timer-atmel-tcb.c`, which again seems incapable of such measurements. Therefore, a new module will probably be needed; the question then becomes: which API to implement.
> 
> As `microchip-tcb-capture.c` uses the Generic Counter Interface, that was obviously a first stop. However, from what I could see, you can only represent (1) the number of times an edge has been encountered, and (2) rotary encodings (quadrature and direction-step decoders); and not the time between edges.

You might find some interesting reading at [1]. A few years ago, I started
adding support for an "edge capture unit" and timer on the TI EQEP quadrature
encoder driver in the counter subsystem. I never found time to keep working on
that to get it merged, but I've actually been looking at it again just last
week. It sounds quite similar, but I didn't consider the possibility of looking
at the duty cycle, only the rate.

[1]: https://lore.kernel.org/linux-iio/20211017013343.3385923-1-david@lechnology.com/

> 
> IIO_ALTVOLTAGE and IIO_CHAN_INFO_FREQUENCY/_PHASE also seemed promising (although the lack of IIO_CHAN_INFO_DUTY_CYCLE already posed a problem), until I saw that all current drivers are frequency *generators*, and not measurers, the latter seems to be completely unimplemented.

A similar case came up somewhat recently [2] where it was suggested to add
IIO_FREQUENCY to be able to measure a clock frequency [3].

[2]: https://lore.kernel.org/linux-iio/20240624173105.909554-1-jbrunet@baylibre.com/
[3]: https://lore.kernel.org/linux-iio/20240629204025.683b1b69@jic23-huawei/
> 
> The only other contender I could find was the Hardware Timestamping Engine (HTE), but again, it's not clear whether (1) the API is even capable of relaying duty cycle information to userspace and (2) if it is, how would one go about implementing it.
> 
> It is also entirely possible I missed a driver or API that could handle this better, if so, please don't keep it to yourselves.

In the PWM subsystem, there is pwm_capture() which allows measuring period and
duty cycle, so could be exactly what you are looking for.

> 
> So, how could one go about implementing such a driver?
> 
> Bence
> 
> 



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Q] Frequency & duty cycle measurement?
  2025-01-21 15:19 [Q] Frequency & duty cycle measurement? Csókás Bence
  2025-01-21 17:45 ` David Lechner
@ 2025-01-27 15:00 ` William Breathitt Gray
  2025-01-30 13:59   ` Csókás Bence
  2025-02-19 22:32 ` Dipen Patel
  2 siblings, 1 reply; 9+ messages in thread
From: William Breathitt Gray @ 2025-01-27 15:00 UTC (permalink / raw)
  To: Csókás Bence
  Cc: linux-iio, linux-kernel@vger.kernel.org, linux-arm-kernel,
	timestamp, Jonathan Cameron, Lars-Peter Clausen, Daniel Lezcano,
	Thomas Gleixner, Dipen Patel, dlechner

[-- Attachment #1: Type: text/plain, Size: 6196 bytes --]

On Tue, Jan 21, 2025 at 04:19:27PM +0100, Csókás Bence wrote:
> Hi all,
> 
> we want to measure the frequency and duty cycle of a signal (relating to
> power consumption) using a hardware timer in our SoC (Microchip SAMA5D2).
> The hardware is capable of taking a snapshot of the timer value into another
> dedicated register pair (RA, RB) on the rising/falling edges, and a small
> `devmem`-based userspace utility was created as a working PoC. Now we want
> to move to a "proper" kernelspace solution.
> 
> However, none of the existing drivers seem to be able to do this; the
> closest was `drivers/counter/microchip-tcb-capture.c`, but that only seems
> to count one type of edge (rising/falling), and cannot give us the time
> between them, which would be needed for duty cycle calculation. The only
> other driver I could find was `drivers/clocksource/timer-atmel-tcb.c`, which
> again seems incapable of such measurements. Therefore, a new module will
> probably be needed; the question then becomes: which API to implement.
> 
> As `microchip-tcb-capture.c` uses the Generic Counter Interface, that was
> obviously a first stop. However, from what I could see, you can only
> represent (1) the number of times an edge has been encountered, and (2)
> rotary encodings (quadrature and direction-step decoders); and not the time
> between edges.
> 
> IIO_ALTVOLTAGE and IIO_CHAN_INFO_FREQUENCY/_PHASE also seemed promising
> (although the lack of IIO_CHAN_INFO_DUTY_CYCLE already posed a problem),
> until I saw that all current drivers are frequency *generators*, and not
> measurers, the latter seems to be completely unimplemented.
> 
> The only other contender I could find was the Hardware Timestamping Engine
> (HTE), but again, it's not clear whether (1) the API is even capable of
> relaying duty cycle information to userspace and (2) if it is, how would one
> go about implementing it.
> 
> It is also entirely possible I missed a driver or API that could handle this
> better, if so, please don't keep it to yourselves.
> 
> So, how could one go about implementing such a driver?
> 
> Bence

Hi Bence,

You could use the Counter chrdev interface to get frequency of counter
events such as rising/falling edges, as well as associating timer values
and snapshots. Do you get an interrupt on each timer snapshot, or is it
just a circular array buffer that gets filled until your purge it? The
implementation might look something like the following.

In the kernel driver, you would push a counter event for each capture; I
assume your hardware issues an interrupt each time a rising/falling edge
occurs:

    static irqreturn_t sama5d2_isr(int irq, void *dev_id)
    {
            struct counter_device *counter = dev_id;
            counter_push_event(counter, COUNTER_EVENT_CAPTURE, 0);
            return IRQ_HANDLED;
    }

In the userspace application, you would setup a Counter "watch" to
collect each desired timer value on the respective Counter events; I
assume RA and RB are Count 0 and Count 1 respectively, but if they
represent something else please let me know:

    static struct counter_watch watches[2] = {
            {
                    /* Component data: Count 0 count */
                    .component.type = COUNTER_COMPONENT_COUNT,
                    .component.scope = COUNTER_SCOPE_COUNT,
                    .component.parent = 0,
                    /* Event type: Capture */
                    .event = COUNTER_EVENT_CAPTURE,
                    /* Device event channel 0 */
                    .channel = 0,
            },
            {
                    /* Component data: Count 1 count */
                    .component.type = COUNTER_COMPONENT_COUNT,
                    .component.scope = COUNTER_SCOPE_COUNT,
                    .component.parent = 1,
                    /* Event type: Capture */
                    .event = COUNTER_EVENT_CAPTURE,
                    /* Device event channel 0 */
                    .channel = 0,
            },
    };
    ...
    int main(void)
    {
            int fd;
            int i;
	    unsigned long long delta_ts, delta_ra, delta_rb;
	    double ra_frequency, rb_frequency, rb_ra;
            struct counter_event first_capture[2], second_capture[2];
            
            /* Open Counter chrdev */
            fd = open("/dev/counter0", O_RDWR);
            
            for (i = 0; i < 2; i++) {
	            /* Register all Counter watches */
                    ioctl(fd, COUNTER_ADD_WATCH_IOCTL, watches + i);
            }
	    /* Start collecting Counter events */
            ioctl(fd, COUNTER_ENABLE_EVENTS_IOCTL);
            
            for (;;) {
	        /* Read first Counter event capture */
            	read(fd, first_capture, sizeof(first_capture));
	        /* Read second Counter event capture */
            	read(fd, second_capture, sizeof(second_capture));
                
		/* Within each capture, timestamp is the same so only
		 * first element of each capture needs to be compared */
		delta_ts = second_capture[0].timestamp - first_capture[0].timestamp;
		/* Compute deltas of timer register pair RA and RB.
		delta_ra = second_capture[0].value - first_capture[0].value;
		delta_rb = second_capture[1].value - first_capture[1].value;
                
		ra_frequency = (double)delta_ra / delta_ts;
		rb_frequency = (double)delta_rb / delta_ts;
		rb_ra = (double)delta_rb / delta_ra;
                
            	printf("RA frequency: %ld\n"
		       "RB frequency: %ld\n"
		       "RB per RA: %ld\n"
            	       ra_frequency, rb_frequency, rb_ra);
            }
            
            return 0;
    }

If RA and RB are provided as a memory buffer on your device, you can
instead expose them via DEFINE_COUNTER_ARRAY_CAPTURE() such as the
ti-ecap-capture driver does, then perform your userspace computations
by utilizing those respective "capture" array attribute values (via
chrdev like the example above or alternatively via sysfs).

Do you think this design would work for your needs?

William Breathitt Gray

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Q] Frequency & duty cycle measurement?
  2025-01-27 15:00 ` William Breathitt Gray
@ 2025-01-30 13:59   ` Csókás Bence
  2025-02-04 23:37     ` William Breathitt Gray
  0 siblings, 1 reply; 9+ messages in thread
From: Csókás Bence @ 2025-01-30 13:59 UTC (permalink / raw)
  To: William Breathitt Gray
  Cc: linux-iio, linux-kernel@vger.kernel.org, linux-arm-kernel,
	timestamp, Jonathan Cameron, Lars-Peter Clausen, Daniel Lezcano,
	Thomas Gleixner, Dipen Patel, dlechner

Hi William,

On 2025. 01. 27. 16:00, William Breathitt Gray wrote:
> In the userspace application, you would setup a Counter "watch" to
> collect each desired timer value on the respective Counter events; I
> assume RA and RB are Count 0 and Count 1 respectively, but if they
> represent something else please let me know:
> 
>      static struct counter_watch watches[2] = {
>              {
>                      /* Component data: Count 0 count */
>                      .component.type = COUNTER_COMPONENT_COUNT,
>                      .component.scope = COUNTER_SCOPE_COUNT,
>                      .component.parent = 0,
>                      /* Event type: Capture */
>                      .event = COUNTER_EVENT_CAPTURE,
>                      /* Device event channel 0 */
>                      .channel = 0,
>              },
>              {
>                      /* Component data: Count 1 count */
>                      .component.type = COUNTER_COMPONENT_COUNT,
>                      .component.scope = COUNTER_SCOPE_COUNT,
>                      .component.parent = 1,
>                      /* Event type: Capture */
>                      .event = COUNTER_EVENT_CAPTURE,
>                      /* Device event channel 0 */
>                      .channel = 0,
>              },
>      };
>      ...
>      int main(void)
>      {
>              int fd;
>              int i;
> 	    unsigned long long delta_ts, delta_ra, delta_rb;
> 	    double ra_frequency, rb_frequency, rb_ra;
>              struct counter_event first_capture[2], second_capture[2];
>              
>              /* Open Counter chrdev */
>              fd = open("/dev/counter0", O_RDWR);
>              
>              for (i = 0; i < 2; i++) {
> 	            /* Register all Counter watches */
>                      ioctl(fd, COUNTER_ADD_WATCH_IOCTL, watches + i);
>              }
> 	    /* Start collecting Counter events */
>              ioctl(fd, COUNTER_ENABLE_EVENTS_IOCTL);
>              
>              for (;;) {
> 	        /* Read first Counter event capture */
>              	read(fd, first_capture, sizeof(first_capture));
> 	        /* Read second Counter event capture */
>              	read(fd, second_capture, sizeof(second_capture));
>                  
> 		/* Within each capture, timestamp is the same so only
> 		 * first element of each capture needs to be compared */
> 		delta_ts = second_capture[0].timestamp - first_capture[0].timestamp;
> 		/* Compute deltas of timer register pair RA and RB.
> 		delta_ra = second_capture[0].value - first_capture[0].value;
> 		delta_rb = second_capture[1].value - first_capture[1].value;
>                  
> 		ra_frequency = (double)delta_ra / delta_ts;
> 		rb_frequency = (double)delta_rb / delta_ts;
> 		rb_ra = (double)delta_rb / delta_ra;
>                  
>              	printf("RA frequency: %ld\n"
> 		       "RB frequency: %ld\n"
> 		       "RB per RA: %ld\n"
>              	       ra_frequency, rb_frequency, rb_ra);
>              }
>              
>              return 0;
>      }
> 
> If RA and RB are provided as a memory buffer on your device, you can
> instead expose them via DEFINE_COUNTER_ARRAY_CAPTURE() such as the
> ti-ecap-capture driver does, then perform your userspace computations
> by utilizing those respective "capture" array attribute values (via
> chrdev like the example above or alternatively via sysfs).

Thanks for your extensive explanation! With 
DEFINE_COUNTER_ARRAY_CAPTURE() I was able to expose RA and RB as 
`/sys/bus/counter/devices/counter0/count0/capture{0,1}`, and could 
verify that by replacing `devmem` calls with read()-reopen(), our PoC 
code still works. Now I want to use the chardev interface, but I 
couldn't find how to set up the watches appropriately. So far I have:

	{
		.component.type = COUNTER_COMPONENT_EXTENSION,
		// also tried COUNTER_COMPONENT_COUNT
		.component.scope = COUNTER_SCOPE_COUNT,
		.component.parent = 0,
		.component.id = X, // also tried this instead:
		// .channel = X,
		.event = COUNTER_EVENT_CAPTURE,
	},

However, with this, the first read() never comes back.

Bence


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Q] Frequency & duty cycle measurement?
  2025-01-30 13:59   ` Csókás Bence
@ 2025-02-04 23:37     ` William Breathitt Gray
  2025-02-05  9:30       ` Csókás Bence
  0 siblings, 1 reply; 9+ messages in thread
From: William Breathitt Gray @ 2025-02-04 23:37 UTC (permalink / raw)
  To: Csókás Bence
  Cc: linux-iio, linux-kernel@vger.kernel.org, linux-arm-kernel,
	timestamp, Jonathan Cameron, Lars-Peter Clausen, Daniel Lezcano,
	Thomas Gleixner, Dipen Patel, dlechner

[-- Attachment #1: Type: text/plain, Size: 3751 bytes --]

On Thu, Jan 30, 2025 at 02:59:20PM +0100, Csókás Bence wrote:
> Hi William,
> 
> On 2025. 01. 27. 16:00, William Breathitt Gray wrote:
> > If RA and RB are provided as a memory buffer on your device, you can
> > instead expose them via DEFINE_COUNTER_ARRAY_CAPTURE() such as the
> > ti-ecap-capture driver does, then perform your userspace computations
> > by utilizing those respective "capture" array attribute values (via
> > chrdev like the example above or alternatively via sysfs).
> 
> Thanks for your extensive explanation! With DEFINE_COUNTER_ARRAY_CAPTURE() I
> was able to expose RA and RB as
> `/sys/bus/counter/devices/counter0/count0/capture{0,1}`, and could verify
> that by replacing `devmem` calls with read()-reopen(), our PoC code still
> works. Now I want to use the chardev interface, but I couldn't find how to
> set up the watches appropriately. So far I have:
> 
> 	{
> 		.component.type = COUNTER_COMPONENT_EXTENSION,
> 		// also tried COUNTER_COMPONENT_COUNT
> 		.component.scope = COUNTER_SCOPE_COUNT,
> 		.component.parent = 0,
> 		.component.id = X, // also tried this instead:
> 		// .channel = X,
> 		.event = COUNTER_EVENT_CAPTURE,
> 	},
> 
> However, with this, the first read() never comes back.
> 
> Bence

Hi Bence,

Are you still having trouble with this? Is "X" the
capture{0,1}_component_id value?

I apologize, the Generic Counter character device interface is
underdocumented so it can be a bit confusing at first; I'll submit a
patch improving the documentation later this cycle when I get a chance.
For now, let's walk through how to create an appropriate Counter watch
for the capture extension components you have.

The first step is to decide which event we'll monitor and on which
channel: we want to monitor Capture events so that's
COUNTER_EVENT_CAPTURE, and we want event channel 0 (n.b. 0 because
that's the channel parameter value passed to counter_push_event() in the
driver).

The next step is to choose the components you wish to watch: Count 0's
capture0 and capture1 extensions. So type is COUNTER_COMPONENT_EXTENSION
because we want to watch extensions, scope is COUNTER_SCOPE_COUNT
because we want Count extensions, and parent is 0 because we want
Count 0's Count extensions.

Finally, we need to set the component id for each extension. You get a
particular component's id by reading the respective *_component_id sysfs
attribute: so for capture{0,1} you would read capture{0,1}_component_id
respectively. These component id values potentially can change with
future driver updates, so for robustness your userspace application
should read the respective *_component_id sysfs attribute itself rather
than hardcoding the component id in the Counter watch.

However, for the sake of simplicity in this example, I'll assume the
component ids are 42 and 43 respectively for capture0 and capture1. That
gives us the following two watches:

        {
                .component.type = COUNTER_COMPONENT_EXTENSION,
                .component.scope = COUNTER_SCOPE_COUNT,
                .component.parent = 0,
                .component.id = 42,
                .event = COUNTER_EVENT_CAPTURE,
                .channel = 0,
        },
        {
                .component.type = COUNTER_COMPONENT_EXTENSION,
                .component.scope = COUNTER_SCOPE_COUNT,
                .component.parent = 0,
                .component.id = 43,
                .event = COUNTER_EVENT_CAPTURE,
                .channel = 0,
        },

Does this resolve your chardev read issue? If you're still having
troubling, just let me know and we can troubleshoot further to figure
out what's going on.

William Breathitt Gray

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Q] Frequency & duty cycle measurement?
  2025-02-04 23:37     ` William Breathitt Gray
@ 2025-02-05  9:30       ` Csókás Bence
  2025-02-05  9:58         ` Csókás Bence
  0 siblings, 1 reply; 9+ messages in thread
From: Csókás Bence @ 2025-02-05  9:30 UTC (permalink / raw)
  To: William Breathitt Gray
  Cc: linux-iio, linux-kernel@vger.kernel.org, linux-arm-kernel,
	timestamp, Jonathan Cameron, Lars-Peter Clausen, Daniel Lezcano,
	Thomas Gleixner, Dipen Patel, dlechner

Hi,

On 2025. 02. 05. 0:37, William Breathitt Gray wrote:
> Are you still having trouble with this? Is "X" the
> capture{0,1}_component_id value?

X is 0/1 from `/sys/bus/counter/devices/counter0/count0/capture{0,1}`, 
which is also equal to the respective `capture{0,1}_component_id`, since 
I don't have any other counters. I checked that beforehand.

> I apologize, the Generic Counter character device interface is
> underdocumented so it can be a bit confusing at first; I'll submit a
> patch improving the documentation later this cycle when I get a chance.
> For now, let's walk through how to create an appropriate Counter watch
> for the capture extension components you have.

After much tinkering and reading of the `counter-chrdev.c` code, I now 
see *something*, although it's much slower to make a measurement than 
the sysfs `reopen()` hack.

> The first step is to decide which event we'll monitor and on which
> channel: we want to monitor Capture events so that's
> COUNTER_EVENT_CAPTURE, and we want event channel 0 (n.b. 0 because
> that's the channel parameter value passed to counter_push_event() in the
> driver).
> 
> The next step is to choose the components you wish to watch: Count 0's
> capture0 and capture1 extensions. So type is COUNTER_COMPONENT_EXTENSION
> because we want to watch extensions, scope is COUNTER_SCOPE_COUNT
> because we want Count extensions, and parent is 0 because we want
> Count 0's Count extensions.
> 
> Finally, we need to set the component id for each extension. You get a
> particular component's id by reading the respective *_component_id sysfs
> attribute: so for capture{0,1} you would read capture{0,1}_component_id
> respectively. These component id values potentially can change with
> future driver updates, so for robustness your userspace application
> should read the respective *_component_id sysfs attribute itself rather
> than hardcoding the component id in the Counter watch.
> 
> However, for the sake of simplicity in this example, I'll assume the
> component ids are 42 and 43 respectively for capture0 and capture1. That
> gives us the following two watches:
> 
>          {
>                  .component.type = COUNTER_COMPONENT_EXTENSION,
>                  .component.scope = COUNTER_SCOPE_COUNT,
>                  .component.parent = 0,
>                  .component.id = 42,
>                  .event = COUNTER_EVENT_CAPTURE,
>                  .channel = 0,
>          },
>          {
>                  .component.type = COUNTER_COMPONENT_EXTENSION,
>                  .component.scope = COUNTER_SCOPE_COUNT,
>                  .component.parent = 0,
>                  .component.id = 43,
>                  .event = COUNTER_EVENT_CAPTURE,
>                  .channel = 0,
>          },
> 
> Does this resolve your chardev read issue? If you're still having
> troubling, just let me know and we can troubleshoot further to figure
> out what's going on.

I had no success using `channel = 0`, only data from `capture0` comes 
back. If I set both `channel` AND `component.id` to X, then I start to 
see similar values than what I get from reading sysfs. (For now I 
hard-coded all values; I agree that the correct way would be to read 
component IDs from sysfs, but this is still a PoC...)

Did I do something wrong in implementing the driver maybe? (See the 
submitted patches.) And any idea as to why I might be seeing the slowdown?

Bence


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Q] Frequency & duty cycle measurement?
  2025-02-05  9:30       ` Csókás Bence
@ 2025-02-05  9:58         ` Csókás Bence
  0 siblings, 0 replies; 9+ messages in thread
From: Csókás Bence @ 2025-02-05  9:58 UTC (permalink / raw)
  To: William Breathitt Gray
  Cc: linux-iio, linux-kernel@vger.kernel.org, linux-arm-kernel,
	timestamp, Jonathan Cameron, Lars-Peter Clausen, Daniel Lezcano,
	Thomas Gleixner, Dipen Patel, dlechner

Hi,

On 2025. 02. 05. 10:30, Csókás Bence wrote:
> Hi,
> 
> On 2025. 02. 05. 0:37, William Breathitt Gray wrote:
>> The first step is to decide which event we'll monitor and on which
>> channel: we want to monitor Capture events so that's
>> COUNTER_EVENT_CAPTURE, and we want event channel 0 (n.b. 0 because
>> that's the channel parameter value passed to counter_push_event() in the
>> driver).

Ah, I push 0 and 1 for the two interrupts... So that's why `channel` has 
to be 0 and 1 as well. Does it make sense to do it this way, or should I 
push on event channel 0 always?

> I had no success using `channel = 0`, only data from `capture0` comes 
> back. If I set both `channel` AND `component.id` to X, then I start to 
> see similar values than what I get from reading sysfs. (For now I 
> hard-coded all values; I agree that the correct way would be to read 
> component IDs from sysfs, but this is still a PoC...)
> 
> Did I do something wrong in implementing the driver maybe? (See the 
> submitted patches.) And any idea as to why I might be seeing the slowdown?

The slowdown is still a mystery though...

Bence


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Q] Frequency & duty cycle measurement?
  2025-01-21 15:19 [Q] Frequency & duty cycle measurement? Csókás Bence
  2025-01-21 17:45 ` David Lechner
  2025-01-27 15:00 ` William Breathitt Gray
@ 2025-02-19 22:32 ` Dipen Patel
  2025-02-26 13:56   ` Csókás Bence
  2 siblings, 1 reply; 9+ messages in thread
From: Dipen Patel @ 2025-02-19 22:32 UTC (permalink / raw)
  To: Csókás Bence, linux-iio, linux-kernel@vger.kernel.org,
	linux-arm-kernel, timestamp
  Cc: William Breathitt Gray, Jonathan Cameron, Lars-Peter Clausen,
	Daniel Lezcano, Thomas Gleixner

On 1/21/25 7:19 AM, Csókás Bence wrote:
> he hardware is capable of taking a snapshot of the timer value into another
> dedicated register pair (RA, RB) on the rising/falling edges, and a small
> `devmem`-based userspace utility was created as a working PoC
I am late to the party :) Seems above statement looks lot like what HTE
subsystem is doing. Right now, only userspace path is through the gpiolib
due to usage that time was limited to GPIOs. However, we can extend HTE to meet
this scenario.

Thanks,
Best Regards,
Dipen Patel

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Q] Frequency & duty cycle measurement?
  2025-02-19 22:32 ` Dipen Patel
@ 2025-02-26 13:56   ` Csókás Bence
  0 siblings, 0 replies; 9+ messages in thread
From: Csókás Bence @ 2025-02-26 13:56 UTC (permalink / raw)
  To: Dipen Patel, linux-iio, linux-kernel@vger.kernel.org,
	linux-arm-kernel, timestamp
  Cc: William Breathitt Gray, Jonathan Cameron, Lars-Peter Clausen,
	Daniel Lezcano, Thomas Gleixner

Hi,

On 2025. 02. 19. 23:32, Dipen Patel wrote:
> On 1/21/25 7:19 AM, Csókás Bence wrote:
>> he hardware is capable of taking a snapshot of the timer value into another
>> dedicated register pair (RA, RB) on the rising/falling edges, and a small
>> `devmem`-based userspace utility was created as a working PoC
> I am late to the party :) Seems above statement looks lot like what HTE
> subsystem is doing. Right now, only userspace path is through the gpiolib
> due to usage that time was limited to GPIOs. However, we can extend HTE to meet
> this scenario.

Yes, I had the same impression. But since there was already a driver for 
this block in the counter subsystem, it was easier to extend that to our 
use case.

> Thanks,
> Best Regards,
> Dipen Patel
> 

Bence


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2025-02-26 13:56 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-01-21 15:19 [Q] Frequency & duty cycle measurement? Csókás Bence
2025-01-21 17:45 ` David Lechner
2025-01-27 15:00 ` William Breathitt Gray
2025-01-30 13:59   ` Csókás Bence
2025-02-04 23:37     ` William Breathitt Gray
2025-02-05  9:30       ` Csókás Bence
2025-02-05  9:58         ` Csókás Bence
2025-02-19 22:32 ` Dipen Patel
2025-02-26 13:56   ` Csókás Bence

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).