Documentation/driver-api/generic-counter.rst GitHub 원문 ↗

Linux 6.18.37 · Driver API

Generic Counter Interface

Signal·Synapse·Count model, driver registration, sysfs·character device와 event ABI를 설명합니다.

Source pathDocumentation/driver-api/generic-counter.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약과 해설

generic-counter.rst:1-573

Generic Counter는 다양한 counter hardware를 Signal, Synapse, Count라는 공통 model로 표현합니다. Driver는 native C type callback과 표준 extension macro를 등록하고, core는 이를 sysfs와 character-device event ABI로 변환합니다.

Event watch는 ioctl로 등록·활성화하며 driver의 `counter_push_event()`가 수집한 component data를 `struct counter_event` 형태로 userspace에 전달합니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 .. SPDX-License-Identifier: GPL-2.0
2
3 =========================
4 Generic Counter Interface
5 =========================
6
7 Introduction
8 ============
9
10 Counter devices are prevalent among a diverse spectrum of industries.
11 The ubiquitous presence of these devices necessitates a common interface
12 and standard of interaction and exposure. This driver API attempts to
13 resolve the issue of duplicate code found among existing counter device
14 drivers by introducing a generic counter interface for consumption. The
15 Generic Counter interface enables drivers to support and expose a common
16 set of components and functionality present in counter devices.
17
18 Theory
19 ======
20
21 Counter devices can vary greatly in design, but regardless of whether
22 some devices are quadrature encoder counters or tally counters, all
23 counter devices consist of a core set of components. This core set of
24 components, shared by all counter devices, is what forms the essence of
25 the Generic Counter interface.
26
27 There are three core components to a counter:
28
29 * Signal:
30 Stream of data to be evaluated by the counter.
31
32 * Synapse:
33 Association of a Signal, and evaluation trigger, with a Count.
34
35 * Count:
36 Accumulation of the effects of connected Synapses.
37
38 SIGNAL
39 ------
40 A Signal represents a stream of data. This is the input data that is
41 evaluated by the counter to determine the count data; e.g. a quadrature
42 signal output line of a rotary encoder. Not all counter devices provide
43 user access to the Signal data, so exposure is optional for drivers.
44
45 When the Signal data is available for user access, the Generic Counter
46 interface provides the following available signal values:
47
48 * SIGNAL_LOW:
49 Signal line is in a low state.
50
51 * SIGNAL_HIGH:
52 Signal line is in a high state.
53
54 A Signal may be associated with one or more Counts.
55
56 SYNAPSE
57 -------
58 A Synapse represents the association of a Signal with a Count. Signal
59 data affects respective Count data, and the Synapse represents this
60 relationship.
61
62 The Synapse action mode specifies the Signal data condition that
63 triggers the respective Count's count function evaluation to update the
64 count data. The Generic Counter interface provides the following
65 available action modes:
66
67 * None:
68 Signal does not trigger the count function. In Pulse-Direction count
69 function mode, this Signal is evaluated as Direction.
70
71 * Rising Edge:
72 Low state transitions to high state.
73
74 * Falling Edge:
75 High state transitions to low state.
76
77 * Both Edges:
78 Any state transition.
79
80 A counter is defined as a set of input signals associated with count
81 data that are generated by the evaluation of the state of the associated
82 input signals as defined by the respective count functions. Within the
83 context of the Generic Counter interface, a counter consists of Counts
84 each associated with a set of Signals, whose respective Synapse
85 instances represent the count function update conditions for the
86 associated Counts.
87
88 A Synapse associates one Signal with one Count.
89
90 COUNT
91 -----
92 A Count represents the accumulation of the effects of connected
93 Synapses; i.e. the count data for a set of Signals. The Generic
94 Counter interface represents the count data as a natural number.
95
96 A Count has a count function mode which represents the update behavior
97 for the count data. The Generic Counter interface provides the following
98 available count function modes:
99
100 * Increase:
101 Accumulated count is incremented.
102
103 * Decrease:
104 Accumulated count is decremented.
105
106 * Pulse-Direction:
107 Rising edges on signal A updates the respective count. The input level
108 of signal B determines direction.
109
110 * Quadrature:
111 A pair of quadrature encoding signals are evaluated to determine
112 position and direction. The following Quadrature modes are available:
113
114 - x1 A:
115 If direction is forward, rising edges on quadrature pair signal A
116 updates the respective count; if the direction is backward, falling
117 edges on quadrature pair signal A updates the respective count.
118 Quadrature encoding determines the direction.
119
120 - x1 B:
121 If direction is forward, rising edges on quadrature pair signal B
122 updates the respective count; if the direction is backward, falling
123 edges on quadrature pair signal B updates the respective count.
124 Quadrature encoding determines the direction.
125
126 - x2 A:
127 Any state transition on quadrature pair signal A updates the
128 respective count. Quadrature encoding determines the direction.
129
130 - x2 B:
131 Any state transition on quadrature pair signal B updates the
132 respective count. Quadrature encoding determines the direction.
133
134 - x4:
135 Any state transition on either quadrature pair signals updates the
136 respective count. Quadrature encoding determines the direction.
137
138 A Count has a set of one or more associated Synapses.
139
140 Paradigm
141 ========
142
143 The most basic counter device may be expressed as a single Count
144 associated with a single Signal via a single Synapse. Take for example
145 a counter device which simply accumulates a count of rising edges on a
146 source input line::
147
148 Count Synapse Signal
149 ----- ------- ------
150 +---------------------+
151 | Data: Count | Rising Edge ________
152 | Function: Increase | <------------- / Source \
153 | | ____________
154 +---------------------+
155
156 In this example, the Signal is a source input line with a pulsing
157 voltage, while the Count is a persistent count value which is repeatedly
158 incremented. The Signal is associated with the respective Count via a
159 Synapse. The increase function is triggered by the Signal data condition
160 specified by the Synapse -- in this case a rising edge condition on the
161 voltage input line. In summary, the counter device existence and
162 behavior is aptly represented by respective Count, Signal, and Synapse
163 components: a rising edge condition triggers an increase function on an
164 accumulating count datum.
165
166 A counter device is not limited to a single Signal; in fact, in theory
167 many Signals may be associated with even a single Count. For example, a
168 quadrature encoder counter device can keep track of position based on
169 the states of two input lines::
170
171 Count Synapse Signal
172 ----- ------- ------
173 +-------------------------+
174 | Data: Position | Both Edges ___
175 | Function: Quadrature x4 | <------------ / A \
176 | | _______
177 | |
178 | | Both Edges ___
179 | | <------------ / B \
180 | | _______
181 +-------------------------+
182
183 In this example, two Signals (quadrature encoder lines A and B) are
184 associated with a single Count: a rising or falling edge on either A or
185 B triggers the "Quadrature x4" function which determines the direction
186 of movement and updates the respective position data. The "Quadrature
187 x4" function is likely implemented in the hardware of the quadrature
188 encoder counter device; the Count, Signals, and Synapses simply
189 represent this hardware behavior and functionality.
190
191 Signals associated with the same Count can have differing Synapse action
192 mode conditions. For example, a quadrature encoder counter device
193 operating in a non-quadrature Pulse-Direction mode could have one input
194 line dedicated for movement and a second input line dedicated for
195 direction::
196
197 Count Synapse Signal
198 ----- ------- ------
199 +---------------------------+
200 | Data: Position | Rising Edge ___
201 | Function: Pulse-Direction | <------------- / A \ (Movement)
202 | | _______
203 | |
204 | | None ___
205 | | <------------- / B \ (Direction)
206 | | _______
207 +---------------------------+
208
209 Only Signal A triggers the "Pulse-Direction" update function, but the
210 instantaneous state of Signal B is still required in order to know the
211 direction so that the position data may be properly updated. Ultimately,
212 both Signals are associated with the same Count via two respective
213 Synapses, but only one Synapse has an active action mode condition which
214 triggers the respective count function while the other is left with a
215 "None" condition action mode to indicate its respective Signal's
216 availability for state evaluation despite its non-triggering mode.
217
218 Keep in mind that the Signal, Synapse, and Count are abstract
219 representations which do not need to be closely married to their
220 respective physical sources. This allows the user of a counter to
221 divorce themselves from the nuances of physical components (such as
222 whether an input line is differential or single-ended) and instead focus
223 on the core idea of what the data and process represent (e.g. position
224 as interpreted from quadrature encoding data).
225
226 Driver API
227 ==========
228
229 Driver authors may utilize the Generic Counter interface in their code
230 by including the include/linux/counter.h header file. This header file
231 provides several core data structures, function prototypes, and macros
232 for defining a counter device.
233
234 .. kernel-doc:: include/linux/counter.h
235 :internal:
236
237 .. kernel-doc:: drivers/counter/counter-core.c
238 :export:
239
240 .. kernel-doc:: drivers/counter/counter-chrdev.c
241 :export:
242
243 Driver Implementation
244 =====================
245
246 To support a counter device, a driver must first allocate the available
247 Counter Signals via counter_signal structures. These Signals should
248 be stored as an array and set to the signals array member of an
249 allocated counter_device structure before the Counter is registered to
250 the system.
251
252 Counter Counts may be allocated via counter_count structures, and
253 respective Counter Signal associations (Synapses) made via
254 counter_synapse structures. Associated counter_synapse structures are
255 stored as an array and set to the synapses array member of the
256 respective counter_count structure. These counter_count structures are
257 set to the counts array member of an allocated counter_device structure
258 before the Counter is registered to the system.
259
260 Driver callbacks must be provided to the counter_device structure in
261 order to communicate with the device: to read and write various Signals
262 and Counts, and to set and get the "action mode" and "function mode" for
263 various Synapses and Counts respectively.
264
265 A counter_device structure is allocated using counter_alloc() and then
266 registered to the system by passing it to the counter_add() function, and
267 unregistered by passing it to the counter_unregister function. There are
268 device managed variants of these functions: devm_counter_alloc() and
269 devm_counter_add().
270
271 The struct counter_comp structure is used to define counter extensions
272 for Signals, Synapses, and Counts.
273
274 The "type" member specifies the type of high-level data (e.g. BOOL,
275 COUNT_DIRECTION, etc.) handled by this extension. The "``*_read``" and
276 "``*_write``" members can then be set by the counter device driver with
277 callbacks to handle that data using native C data types (i.e. u8, u64,
278 etc.).
279
280 Convenience macros such as ``COUNTER_COMP_COUNT_U64`` are provided for
281 use by driver authors. In particular, driver authors are expected to use
282 the provided macros for standard Counter subsystem attributes in order
283 to maintain a consistent interface for userspace. For example, a counter
284 device driver may define several standard attributes like so::
285
286 struct counter_comp count_ext[] = {
287 COUNTER_COMP_DIRECTION(count_direction_read),
288 COUNTER_COMP_ENABLE(count_enable_read, count_enable_write),
289 COUNTER_COMP_CEILING(count_ceiling_read, count_ceiling_write),
290 };
291
292 This makes it simple to see, add, and modify the attributes that are
293 supported by this driver ("direction", "enable", and "ceiling") and to
294 maintain this code without getting lost in a web of struct braces.
295
296 Callbacks must match the function type expected for the respective
297 component or extension. These function types are defined in the struct
298 counter_comp structure as the "``*_read``" and "``*_write``" union
299 members.
300
301 The corresponding callback prototypes for the extensions mentioned in
302 the previous example above would be::
303
304 int count_direction_read(struct counter_device *counter,
305 struct counter_count *count,
306 enum counter_count_direction *direction);
307 int count_enable_read(struct counter_device *counter,
308 struct counter_count *count, u8 *enable);
309 int count_enable_write(struct counter_device *counter,
310 struct counter_count *count, u8 enable);
311 int count_ceiling_read(struct counter_device *counter,
312 struct counter_count *count, u64 *ceiling);
313 int count_ceiling_write(struct counter_device *counter,
314 struct counter_count *count, u64 ceiling);
315
316 Determining the type of extension to create is a matter of scope.
317
318 * Signal extensions are attributes that expose information/control
319 specific to a Signal. These types of attributes will exist under a
320 Signal's directory in sysfs.
321
322 For example, if you have an invert feature for a Signal, you can have
323 a Signal extension called "invert" that toggles that feature:
324 /sys/bus/counter/devices/counterX/signalY/invert
325
326 * Count extensions are attributes that expose information/control
327 specific to a Count. These type of attributes will exist under a
328 Count's directory in sysfs.
329
330 For example, if you want to pause/unpause a Count from updating, you
331 can have a Count extension called "enable" that toggles such:
332 /sys/bus/counter/devices/counterX/countY/enable
333
334 * Device extensions are attributes that expose information/control
335 non-specific to a particular Count or Signal. This is where you would
336 put your global features or other miscellaneous functionality.
337
338 For example, if your device has an overtemp sensor, you can report the
339 chip overheated via a device extension called "error_overtemp":
340 /sys/bus/counter/devices/counterX/error_overtemp
341
342 Subsystem Architecture
343 ======================
344
345 Counter drivers pass and take data natively (i.e. ``u8``, ``u64``, etc.)
346 and the shared counter module handles the translation between the sysfs
347 interface. This guarantees a standard userspace interface for all
348 counter drivers, and enables a Generic Counter chrdev interface via a
349 generalized device driver ABI.
350
351 A high-level view of how a count value is passed down from a counter
352 driver is exemplified by the following. The driver callbacks are first
353 registered to the Counter core component for use by the Counter
354 userspace interface components::
355
356 Driver callbacks registration:
357 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
358 +----------------------------+
359 | Counter device driver |
360 +----------------------------+
361 | Processes data from device |
362 +----------------------------+
363 |
364 -------------------
365 / driver callbacks /
366 -------------------
367 |
368 V
369 +----------------------+
370 | Counter core |
371 +----------------------+
372 | Routes device driver |
373 | callbacks to the |
374 | userspace interfaces |
375 +----------------------+
376 |
377 -------------------
378 / driver callbacks /
379 -------------------
380 |
381 +---------------+---------------+
382 | |
383 V V
384 +--------------------+ +---------------------+
385 | Counter sysfs | | Counter chrdev |
386 +--------------------+ +---------------------+
387 | Translates to the | | Translates to the |
388 | standard Counter | | standard Counter |
389 | sysfs output | | character device |
390 +--------------------+ +---------------------+
391
392 Thereafter, data can be transferred directly between the Counter device
393 driver and Counter userspace interface::
394
395 Count data request:
396 ~~~~~~~~~~~~~~~~~~~
397 ----------------------
398 / Counter device \
399 +----------------------+
400 | Count register: 0x28 |
401 +----------------------+
402 |
403 -----------------
404 / raw count data /
405 -----------------
406 |
407 V
408 +----------------------------+
409 | Counter device driver |
410 +----------------------------+
411 | Processes data from device |
412 |----------------------------|
413 | Type: u64 |
414 | Value: 42 |
415 +----------------------------+
416 |
417 ----------
418 / u64 /
419 ----------
420 |
421 +---------------+---------------+
422 | |
423 V V
424 +--------------------+ +---------------------+
425 | Counter sysfs | | Counter chrdev |
426 +--------------------+ +---------------------+
427 | Translates to the | | Translates to the |
428 | standard Counter | | standard Counter |
429 | sysfs output | | character device |
430 |--------------------| |---------------------|
431 | Type: const char * | | Type: u64 |
432 | Value: "42" | | Value: 42 |
433 +--------------------+ +---------------------+
434 | |
435 --------------- -----------------------
436 / const char * / / struct counter_event /
437 --------------- -----------------------
438 | |
439 | V
440 | +-----------+
441 | | read |
442 | +-----------+
443 | \ Count: 42 /
444 | -----------
445 |
446 V
447 +--------------------------------------------------+
448 | `/sys/bus/counter/devices/counterX/countY/count` |
449 +--------------------------------------------------+
450 \ Count: "42" /
451 --------------------------------------------------
452
453 There are four primary components involved:
454
455 Counter device driver
456 ---------------------
457 Communicates with the hardware device to read/write data; e.g. counter
458 drivers for quadrature encoders, timers, etc.
459
460 Counter core
461 ------------
462 Registers the counter device driver to the system so that the respective
463 callbacks are called during userspace interaction.
464
465 Counter sysfs
466 -------------
467 Translates counter data to the standard Counter sysfs interface format
468 and vice versa.
469
470 Please refer to the Documentation/ABI/testing/sysfs-bus-counter file
471 for a detailed breakdown of the available Generic Counter interface
472 sysfs attributes.
473
474 Counter chrdev
475 --------------
476 Translates Counter events to the standard Counter character device; data
477 is transferred via standard character device read calls, while Counter
478 events are configured via ioctl calls.
479
480 Sysfs Interface
481 ===============
482
483 Several sysfs attributes are generated by the Generic Counter interface,
484 and reside under the ``/sys/bus/counter/devices/counterX`` directory,
485 where ``X`` is to the respective counter device id. Please see
486 Documentation/ABI/testing/sysfs-bus-counter for detailed information
487 on each Generic Counter interface sysfs attribute.
488
489 Through these sysfs attributes, programs and scripts may interact with
490 the Generic Counter paradigm Counts, Signals, and Synapses of respective
491 counter devices.
492
493 Counter Character Device
494 ========================
495
496 Counter character device nodes are created under the ``/dev`` directory
497 as ``counterX``, where ``X`` is the respective counter device id.
498 Defines for the standard Counter data types are exposed via the
499 userspace ``include/uapi/linux/counter.h`` file.
500
501 Counter events
502 --------------
503 Counter device drivers can support Counter events by utilizing the
504 ``counter_push_event`` function::
505
506 void counter_push_event(struct counter_device *const counter, const u8 event,
507 const u8 channel);
508
509 The event id is specified by the ``event`` parameter; the event channel
510 id is specified by the ``channel`` parameter. When this function is
511 called, the Counter data associated with the respective event is
512 gathered, and a ``struct counter_event`` is generated for each datum and
513 pushed to userspace.
514
515 Counter events can be configured by users to report various Counter
516 data of interest. This can be conceptualized as a list of Counter
517 component read calls to perform. For example:
518
519 +------------------------+------------------------+
520 | COUNTER_EVENT_OVERFLOW | COUNTER_EVENT_INDEX |
521 +========================+========================+
522 | Channel 0 | Channel 0 |
523 +------------------------+------------------------+
524 | * Count 0 | * Signal 0 |
525 | * Count 1 | * Signal 0 Extension 0 |
526 | * Signal 3 | * Extension 4 |
527 | * Count 4 Extension 2 +------------------------+
528 | * Signal 5 Extension 0 | Channel 1 |
529 | +------------------------+
530 | | * Signal 4 |
531 | | * Signal 4 Extension 0 |
532 | | * Count 7 |
533 +------------------------+------------------------+
534
535 When ``counter_push_event(counter, COUNTER_EVENT_INDEX, 1)`` is called
536 for example, it will go down the list for the ``COUNTER_EVENT_INDEX``
537 event channel 1 and execute the read callbacks for Signal 4, Signal 4
538 Extension 0, and Count 7 -- the data returned for each is pushed to a
539 kfifo as a ``struct counter_event``, which userspace can retrieve via a
540 standard read operation on the respective character device node.
541
542 Userspace
543 ---------
544 Userspace applications can configure Counter events via ioctl operations
545 on the Counter character device node. There following ioctl codes are
546 supported and provided by the ``linux/counter.h`` userspace header file:
547
548 * :c:macro:`COUNTER_ADD_WATCH_IOCTL`
549
550 * :c:macro:`COUNTER_ENABLE_EVENTS_IOCTL`
551
552 * :c:macro:`COUNTER_DISABLE_EVENTS_IOCTL`
553
554 To configure events to gather Counter data, users first populate a
555 ``struct counter_watch`` with the relevant event id, event channel id,
556 and the information for the desired Counter component from which to
557 read, and then pass it via the ``COUNTER_ADD_WATCH_IOCTL`` ioctl
558 command.
559
560 Note that an event can be watched without gathering Counter data by
561 setting the ``component.type`` member equal to
562 ``COUNTER_COMPONENT_NONE``. With this configuration the Counter
563 character device will simply populate the event timestamps for those
564 respective ``struct counter_event`` elements and ignore the component
565 value.
566
567 The ``COUNTER_ADD_WATCH_IOCTL`` command will buffer these Counter
568 watches. When ready, the ``COUNTER_ENABLE_EVENTS_IOCTL`` ioctl command
569 may be used to activate these Counter watches.
570
571 Userspace applications can then execute a ``read`` operation (optionally
572 calling ``poll`` first) on the Counter character device node to retrieve
573 ``struct counter_event`` elements with the desired data.
574

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

Generic Counter Interface 소개

1-17

이 문서는 `GPL-2.0` SPDX license를 사용하며 제목은 `Generic Counter Interface`입니다.

Counter device는 다양한 산업 영역에서 널리 사용되므로 공통 interface와 표준화된 interaction·exposure 방식이 필요합니다. 이 driver API는 기존 counter driver 사이의 중복 code를 줄이기 위해 generic counter interface를 제공합니다.

Generic Counter interface를 사용하면 driver가 counter device에 공통적으로 존재하는 component와 기능 집합을 지원하고 노출할 수 있습니다.

Counter의 세 핵심 component

18-37

Counter device는 quadrature encoder counter나 tally counter 등 설계가 크게 다를 수 있지만 모두 공통 핵심 component를 가집니다. 이 공통 집합이 Generic Counter interface의 본질입니다.

  • `Signal`: counter가 평가할 data stream
  • `Synapse`: Signal과 Count를 연결하고 평가 trigger를 지정하는 association
  • `Count`: 연결된 Synapse의 효과를 누적한 값
Generic Counter 핵심 관계
Signal data stream 입력Synapse가 action condition 평가조건이 맞으면 Count function 실행Count data 누적 또는 갱신

Signal condition이 Synapse를 통해 Count update function을 trigger합니다.

SIGNAL

38-55

Signal은 counter가 count data를 결정하기 위해 평가하는 input data stream입니다. 예를 들면 rotary encoder의 quadrature signal output line입니다. 모든 counter device가 Signal data에 대한 user access를 제공하지는 않으므로 driver의 Signal 노출은 선택 사항입니다.

Signal data를 user에게 제공할 때 Generic Counter interface는 두 값을 정의합니다. `SIGNAL_LOW`는 signal line이 low state임을, `SIGNAL_HIGH`는 high state임을 뜻합니다.

한 Signal은 하나 이상의 Count와 연결될 수 있습니다.

Generic Counter Signal 값
의미
SIGNAL_LOWSignal line이 low state
SIGNAL_HIGHSignal line이 high state

User access가 가능한 Signal line의 논리 상태입니다.

SYNAPSE

56-89

Synapse는 Signal과 Count의 연결을 나타냅니다. Signal data가 해당 Count data에 미치는 관계를 표현합니다.

Synapse action mode는 연결된 Count의 count function 평가를 trigger해 count data를 갱신할 Signal condition을 지정합니다.

`None`에서는 Signal이 count function을 trigger하지 않습니다. 다만 Pulse-Direction count function mode에서는 이 Signal을 Direction으로 평가합니다. `Rising Edge`는 low에서 high로, `Falling Edge`는 high에서 low로 바뀌는 전이이며, `Both Edges`는 모든 state transition입니다.

Counter는 연결된 input Signal의 state를 각 count function 정의에 따라 평가해 생성한 Count data의 집합입니다. 각 Count에 연결된 Signal과 Synapse instance가 count function update condition을 나타냅니다. 하나의 Synapse는 정확히 하나의 Signal과 하나의 Count를 연결합니다.

Synapse action mode
Action modeTrigger condition비고
NoneTrigger하지 않음Pulse-Direction에서는 Direction state 평가
Rising EdgeLow → High상승 edge
Falling EdgeHigh → Low하강 edge
Both Edges모든 state transition상승·하강 모두

Count function을 실행시키는 Signal condition입니다.

COUNT

90-139

Count는 연결된 Synapse 효과의 누적, 즉 Signal 집합에 대한 count data를 나타냅니다. Generic Counter interface는 count data를 natural number로 표현합니다.

Count의 count function mode는 count data를 갱신하는 동작을 정의합니다. `Increase`는 누적 count를 증가시키고 `Decrease`는 감소시킵니다.

`Pulse-Direction`에서는 Signal A의 rising edge가 Count를 갱신하고 Signal B의 input level이 방향을 결정합니다.

`Quadrature`는 quadrature encoding Signal pair를 평가해 position과 direction을 결정합니다. `x1 A`와 `x1 B`는 진행 방향에 따라 해당 Signal의 rising 또는 falling edge에서 갱신합니다. `x2 A`와 `x2 B`는 해당 Signal의 모든 transition에서 갱신하며, `x4`는 pair의 어느 Signal에서든 발생한 모든 transition에서 갱신합니다. 모든 mode에서 quadrature encoding이 방향을 결정합니다.

하나의 Count에는 하나 이상의 Synapse 집합이 연결됩니다.

Count function mode
ModeUpdate 조건방향 결정
IncreaseTrigger마다 증가해당 없음
DecreaseTrigger마다 감소해당 없음
Pulse-DirectionSignal A rising edgeSignal B level
Quadrature x1 A/B선택 Signal의 방향별 한 edgeQuadrature encoding
Quadrature x2 A/B선택 Signal의 모든 edgeQuadrature encoding
Quadrature x4A와 B의 모든 edgeQuadrature encoding

Count data update 방식과 사용하는 Signal edge입니다.

Counter paradigm 예제

140-225

가장 기본적인 counter device는 하나의 Synapse를 통해 하나의 Signal에 연결된 하나의 Count로 표현할 수 있습니다. Source input line의 rising edge를 누적하는 경우, pulsing voltage Signal의 rising edge가 Synapse condition을 만족하면 `Increase` function이 persistent Count를 증가시킵니다.

Rising-edge tally counter
Signal: pulsing Source inputSynapse action: Rising EdgeCount function: IncreaseCount data: 누적 Count

원문의 단일 Signal·Synapse·Count ASCII 그림을 구조화했습니다.

Counter device는 하나의 Signal에 제한되지 않습니다. Quadrature encoder에서는 Signal A와 B가 하나의 position Count에 연결되고, 어느 Signal의 rising 또는 falling edge든 `Quadrature x4` function을 trigger해 이동 방향을 결정하고 position을 갱신합니다. 이 function은 보통 hardware에 구현되며 Count·Signal·Synapse는 그 동작을 추상화합니다.

Quadrature x4 관계
SignalSynapse actionCount dataCount function
ABoth EdgesPositionQuadrature x4
BBoth EdgesPositionQuadrature x4

원문의 두 Signal quadrature ASCII 그림을 표로 재구성했습니다.

같은 Count에 연결된 Signal은 서로 다른 Synapse action condition을 가질 수 있습니다. Non-quadrature Pulse-Direction mode에서는 Signal A가 movement pulse를 담당해 rising edge로 update function을 trigger하고, Signal B는 direction state만 제공합니다. B의 action mode는 `None`이지만 방향 평가를 위해 state를 읽을 수 있습니다.

Pulse-Direction 관계
Signal역할Synapse actionCount function
AMovementRising EdgePulse-Direction trigger
BDirectionNoneState evaluation only

원문의 movement·direction Signal ASCII 그림을 표로 재구성했습니다.

Signal, Synapse, Count는 물리 source와 반드시 밀접하게 대응할 필요가 없는 추상 표현입니다. 사용자는 input line이 differential인지 single-ended인지 같은 물리 세부 사항에서 벗어나 quadrature data에서 해석한 position처럼 data와 process의 핵심 의미에 집중할 수 있습니다.

Driver API

226-242

Driver 작성자는 `include/linux/counter.h`를 include해 Generic Counter interface를 사용할 수 있습니다. 이 header는 counter device 정의에 필요한 핵심 data structure, function prototype과 macro를 제공합니다.

.. kernel-doc:: include/linux/counter.h
   :internal:

Core registration function 문서는 `drivers/counter/counter-core.c`에서 export된 항목을 가져옵니다.

.. kernel-doc:: drivers/counter/counter-core.c
   :export:

Character device function 문서는 `drivers/counter/counter-chrdev.c`에서 export된 항목을 가져옵니다.

.. kernel-doc:: drivers/counter/counter-chrdev.c
   :export:

Counter driver 구현

243-315

Counter device를 지원하려면 먼저 사용 가능한 Signal을 `counter_signal` structure로 할당해 array에 저장하고, system 등록 전에 할당한 `counter_device`의 `signals` array member에 설정합니다.

Count는 `counter_count` structure로 할당합니다. Signal과 Count의 association인 Synapse는 `counter_synapse` structure로 만들고 array에 저장해 해당 `counter_count`의 `synapses` member에 설정합니다. 완성한 `counter_count` array는 등록 전에 `counter_device.counts`에 연결합니다.

`counter_device`에는 device와 통신하는 callback을 제공해야 합니다. Callback은 Signal·Count를 읽고 쓰며, Synapse의 action mode와 Count의 function mode를 설정하고 조회합니다.

`counter_alloc()`으로 `counter_device`를 할당하고 `counter_add()`로 등록하며 `counter_unregister()`로 해제합니다. Device-managed variant는 `devm_counter_alloc()`과 `devm_counter_add()`입니다.

`struct counter_comp`는 Signal, Synapse, Count의 extension을 정의합니다. `type` member는 `BOOL`, `COUNT_DIRECTION` 같은 high-level data type을 지정하며, `*_read`와 `*_write` callback은 `u8`, `u64` 같은 native C type으로 data를 처리합니다.

Driver 작성자는 userspace interface의 일관성을 위해 `COUNTER_COMP_COUNT_U64` 같은 convenience macro와 표준 Counter attribute macro를 사용해야 합니다. 다음 예제는 `direction`, `enable`, `ceiling` attribute를 정의합니다.

struct counter_comp count_ext[] = {
        COUNTER_COMP_DIRECTION(count_direction_read),
        COUNTER_COMP_ENABLE(count_enable_read, count_enable_write),
        COUNTER_COMP_CEILING(count_ceiling_read, count_ceiling_write),
};

이 방식은 복잡한 structure brace에 묻히지 않고 driver가 지원하는 attribute를 확인·추가·수정하기 쉽게 합니다. Callback은 `struct counter_comp`의 `*_read`, `*_write` union member가 요구하는 function type과 일치해야 합니다.

int count_direction_read(struct counter_device *counter,
                         struct counter_count *count,
                         enum counter_count_direction *direction);
int count_enable_read(struct counter_device *counter,
                      struct counter_count *count, u8 *enable);
int count_enable_write(struct counter_device *counter,
                       struct counter_count *count, u8 enable);
int count_ceiling_read(struct counter_device *counter,
                       struct counter_count *count, u64 *ceiling);
int count_ceiling_write(struct counter_device *counter,
                        struct counter_count *count, u64 ceiling);
Counter device 등록 구성
counter_signal array 준비counter_synapse array로 Signal과 Count 연결counter_count array 준비counter_device.signals와 counts 설정Driver callback과 extension 연결counter_add() 또는 devm_counter_add()

Signal·Synapse·Count를 조립해 counter_device를 등록하는 순서입니다.

Counter extension scope

316-341

어떤 extension type을 만들지는 attribute의 scope로 결정합니다.

Signal extension은 특정 Signal의 정보나 제어를 노출하며 해당 Signal sysfs directory 아래에 존재합니다. 예를 들어 Signal invert 기능은 `/sys/bus/counter/devices/counterX/signalY/invert`로 제공할 수 있습니다.

Count extension은 특정 Count의 정보나 제어를 노출하며 Count directory 아래에 존재합니다. Count update를 pause·unpause하는 `enable`은 `/sys/bus/counter/devices/counterX/countY/enable`로 제공할 수 있습니다.

Device extension은 특정 Count나 Signal에 종속되지 않은 global 또는 miscellaneous 기능을 노출합니다. Overtemperature sensor 상태는 `/sys/bus/counter/devices/counterX/error_overtemp` 같은 device extension으로 보고할 수 있습니다.

Counter extension scope
Scope대상예제 path
Signal특정 Signal/sys/bus/counter/devices/counterX/signalY/invert
Count특정 Count/sys/bus/counter/devices/counterX/countY/enable
DeviceGlobal·miscellaneous/sys/bus/counter/devices/counterX/error_overtemp

Extension의 소유 component와 sysfs 위치 예제입니다.

Subsystem architecture

342-452

Counter driver는 `u8`, `u64` 같은 native type으로 data를 주고받고 shared counter module이 sysfs interface 형식으로 변환합니다. 이 구조는 모든 counter driver에 표준 userspace interface를 보장하고 일반화된 device driver ABI를 통해 Generic Counter chrdev interface를 제공합니다.

먼저 driver callback을 Counter core에 등록하면 core가 userspace interface component인 Counter sysfs와 Counter chrdev로 callback을 route합니다.

Counter driver callback 등록 경로
Counter device driver가 hardware data 처리Driver callback 등록Counter core가 callback routeCounter sysfs가 표준 sysfs output으로 변환Counter chrdev가 표준 character device로 변환

원문의 callback registration ASCII 그림을 구조화했습니다.

그 뒤 data는 Counter device driver와 userspace interface 사이에서 직접 전달됩니다. 예제에서 hardware count register `0x28`의 raw value를 driver가 `u64` 값 `42`로 처리합니다. Sysfs는 이를 `const char *` 문자열 `"42"`로 변환해 `/sys/bus/counter/devices/counterX/countY/count`에 제공하고, chrdev는 `u64` 42를 `struct counter_event`로 전달해 `read`에서 반환합니다.

Count value 42의 userspace 변환
단계TypeValue·출력
Hardware registerRaw count dataRegister 0x28
Counter driveru6442
Counter sysfsconst char *"42" at countY/count
Counter chrdevu64 in struct counter_event42 via read

원문의 count data request ASCII 흐름을 interface별 data type으로 정리했습니다.

Subsystem의 네 component

453-479

Counter subsystem에는 네 주요 component가 관여합니다.

Counter device driver는 quadrature encoder나 timer 같은 hardware device와 통신해 data를 읽고 씁니다. Counter core는 driver를 system에 등록하고 userspace interaction 중 적절한 callback을 호출합니다.

Counter sysfs는 counter data를 표준 Counter sysfs interface 형식으로 상호 변환합니다. 사용 가능한 attribute의 자세한 설명은 `Documentation/ABI/testing/sysfs-bus-counter`를 참조합니다.

Counter chrdev는 Counter event를 표준 Counter character device로 변환합니다. Data는 일반 character device `read` call로 전달하고 event는 `ioctl` call로 구성합니다.

Generic Counter subsystem component
Component책임
Counter device driverHardware data read·write
Counter coreDriver 등록과 callback dispatch
Counter sysfs표준 sysfs 형식 변환
Counter chrdevEvent·ioctl·read character ABI

Hardware에서 userspace까지 각 component의 책임입니다.

Sysfs interface

480-492

Generic Counter interface가 생성하는 sysfs attribute는 `/sys/bus/counter/devices/counterX` 아래에 위치하며 `X`는 counter device id입니다. 각 attribute의 상세 정보는 `Documentation/ABI/testing/sysfs-bus-counter`를 참조합니다.

Program과 script는 이 sysfs attribute를 통해 각 counter device의 Count, Signal, Synapse와 상호 작용할 수 있습니다.

Counter character device와 event

493-541

Counter character device node는 `/dev/counterX`로 생성되며 `X`는 counter device id입니다. 표준 Counter data type define은 userspace header `include/uapi/linux/counter.h`에서 제공합니다.

Counter device driver는 `counter_push_event` function으로 Counter event를 지원할 수 있습니다.

void counter_push_event(struct counter_device *const counter, const u8 event,
                        const u8 channel);

`event` parameter는 event id, `channel` parameter는 event channel id입니다. Function을 호출하면 해당 event와 연결된 Counter data를 수집해 각 datum마다 `struct counter_event`를 만들고 userspace로 push합니다.

User는 관심 있는 Counter data를 보고하도록 event를 구성할 수 있습니다. 이는 실행할 Counter component read call 목록으로 볼 수 있습니다.

Counter event channel watch 예제
EventChannel읽을 component
COUNTER_EVENT_OVERFLOW0Count 0; Count 1; Signal 3; Count 4 Extension 2; Signal 5 Extension 0
COUNTER_EVENT_INDEX0Signal 0; Signal 0 Extension 0; Extension 4
COUNTER_EVENT_INDEX1Signal 4; Signal 4 Extension 0; Count 7

원문의 COUNTER_EVENT_OVERFLOW·INDEX channel 표를 구조화했습니다.

예를 들어 `counter_push_event(counter, COUNTER_EVENT_INDEX, 1)`을 호출하면 INDEX event channel 1 목록을 따라 Signal 4, Signal 4 Extension 0, Count 7의 read callback을 실행합니다. 각 결과는 `struct counter_event`로 `kfifo`에 push되며 userspace가 해당 character device node의 일반 `read` operation으로 가져옵니다.

Userspace event 구성

542-573

Userspace application은 Counter character device node의 `ioctl` operation으로 event를 구성합니다. `linux/counter.h` userspace header는 `COUNTER_ADD_WATCH_IOCTL`, `COUNTER_ENABLE_EVENTS_IOCTL`, `COUNTER_DISABLE_EVENTS_IOCTL`을 제공합니다.

Counter data를 수집할 event를 구성하려면 `struct counter_watch`에 event id, event channel id, 읽을 Counter component 정보를 채운 뒤 `COUNTER_ADD_WATCH_IOCTL`로 전달합니다.

`component.type`을 `COUNTER_COMPONENT_NONE`으로 설정하면 Counter data를 수집하지 않고 event만 watch할 수 있습니다. 이 경우 character device는 해당 `struct counter_event` element의 timestamp만 채우고 component value는 무시합니다.

`COUNTER_ADD_WATCH_IOCTL`은 watch를 buffer합니다. 준비가 끝나면 `COUNTER_ENABLE_EVENTS_IOCTL`로 활성화합니다. 그 후 application은 필요하면 먼저 `poll`을 호출하고 character device node에서 `read`를 실행해 원하는 data가 담긴 `struct counter_event` element를 가져옵니다.

Userspace Counter event workflow
struct counter_watch 작성COUNTER_ADD_WATCH_IOCTL로 watch bufferCOUNTER_ENABLE_EVENTS_IOCTL로 활성화Driver가 counter_push_event() 호출필요하면 poll()로 준비 확인read()로 struct counter_event 수신COUNTER_DISABLE_EVENTS_IOCTL로 비활성화

Watch 등록부터 event data read까지의 ioctl·I/O 순서입니다.