docs: counter: Update to reflect sysfs internalization

The Counter subsystem architecture and driver implementations have
changed in order to handle Counter sysfs interactions in a more
consistent way. This patch updates the Generic Counter interface
documentation to reflect the changes.

Reviewed-by: David Lechner <david@lechnology.com>
Signed-off-by: William Breathitt Gray <vilhelm.gray@gmail.com>
Link: https://lore.kernel.org/r/91cded13c0145c0d3d0acfe765a2ccb6c9af7c3b.1630031207.git.vilhelm.gray@gmail.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
This commit is contained in:
William Breathitt Gray 2021-08-27 12:47:49 +09:00 committed by Jonathan Cameron
parent 712392f558
commit de8daf30af
2 changed files with 174 additions and 56 deletions

View file

@ -286,7 +286,14 @@ What: /sys/bus/counter/devices/counterX/signalY/signal
KernelVersion: 5.2
Contact: linux-iio@vger.kernel.org
Description:
Signal data of Signal Y represented as a string.
Signal level state of Signal Y. The following signal level
states are available:
low:
Low level state.
high:
High level state.
What: /sys/bus/counter/devices/counterX/signalY/synchronous_mode
KernelVersion: 5.2

View file

@ -250,8 +250,8 @@ for defining a counter device.
.. kernel-doc:: drivers/counter/counter.c
:export:
Implementation
==============
Driver Implementation
=====================
To support a counter device, a driver must first allocate the available
Counter Signals via counter_signal structures. These Signals should
@ -267,25 +267,61 @@ respective counter_count structure. These counter_count structures are
set to the counts array member of an allocated counter_device structure
before the Counter is registered to the system.
Driver callbacks should be provided to the counter_device structure via
a constant counter_ops structure in order to communicate with the
device: to read and write various Signals and Counts, and to set and get
the "action mode" and "function mode" for various Synapses and Counts
respectively.
Driver callbacks must be provided to the counter_device structure in
order to communicate with the device: to read and write various Signals
and Counts, and to set and get the "action mode" and "function mode" for
various Synapses and Counts respectively.
A defined counter_device structure may be registered to the system by
passing it to the counter_register function, and unregistered by passing
it to the counter_unregister function. Similarly, the
devm_counter_register and devm_counter_unregister functions may be used
if device memory-managed registration is desired.
devm_counter_register function may be used if device memory-managed
registration is desired.
Extension sysfs attributes can be created for auxiliary functionality
and data by passing in defined counter_device_ext, counter_count_ext,
and counter_signal_ext structures. In these cases, the
counter_device_ext structure is used for global/miscellaneous exposure
and configuration of the respective Counter device, while the
counter_count_ext and counter_signal_ext structures allow for auxiliary
exposure and configuration of a specific Count or Signal respectively.
The struct counter_comp structure is used to define counter extensions
for Signals, Synapses, and Counts.
The "type" member specifies the type of high-level data (e.g. BOOL,
COUNT_DIRECTION, etc.) handled by this extension. The "``*_read``" and
"``*_write``" members can then be set by the counter device driver with
callbacks to handle that data using native C data types (i.e. u8, u64,
etc.).
Convenience macros such as ``COUNTER_COMP_COUNT_U64`` are provided for
use by driver authors. In particular, driver authors are expected to use
the provided macros for standard Counter subsystem attributes in order
to maintain a consistent interface for userspace. For example, a counter
device driver may define several standard attributes like so::
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),
};
This makes it simple to see, add, and modify the attributes that are
supported by this driver ("direction", "enable", and "ceiling") and to
maintain this code without getting lost in a web of struct braces.
Callbacks must match the function type expected for the respective
component or extension. These function types are defined in the struct
counter_comp structure as the "``*_read``" and "``*_write``" union
members.
The corresponding callback prototypes for the extensions mentioned in
the previous example above would be::
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);
Determining the type of extension to create is a matter of scope.
@ -313,52 +349,127 @@ Determining the type of extension to create is a matter of scope.
chip overheated via a device extension called "error_overtemp":
/sys/bus/counter/devices/counterX/error_overtemp
Architecture
============
Subsystem Architecture
======================
When the Generic Counter interface counter module is loaded, the
counter_init function is called which registers a bus_type named
"counter" to the system. Subsequently, when the module is unloaded, the
counter_exit function is called which unregisters the bus_type named
"counter" from the system.
Counter drivers pass and take data natively (i.e. ``u8``, ``u64``, etc.)
and the shared counter module handles the translation between the sysfs
interface. This guarantees a standard userspace interface for all
counter drivers, and enables a Generic Counter chrdev interface via a
generalized device driver ABI.
Counter devices are registered to the system via the counter_register
function, and later removed via the counter_unregister function. The
counter_register function establishes a unique ID for the Counter
device and creates a respective sysfs directory, where X is the
mentioned unique ID:
A high-level view of how a count value is passed down from a counter
driver is exemplified by the following. The driver callbacks are first
registered to the Counter core component for use by the Counter
userspace interface components::
/sys/bus/counter/devices/counterX
Driver callbacks registration:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+----------------------------+
| Counter device driver |
+----------------------------+
| Processes data from device |
+----------------------------+
|
-------------------
/ driver callbacks /
-------------------
|
V
+----------------------+
| Counter core |
+----------------------+
| Routes device driver |
| callbacks to the |
| userspace interfaces |
+----------------------+
|
-------------------
/ driver callbacks /
-------------------
|
+---------------+
|
V
+--------------------+
| Counter sysfs |
+--------------------+
| Translates to the |
| standard Counter |
| sysfs output |
+--------------------+
Sysfs attributes are created within the counterX directory to expose
functionality, configurations, and data relating to the Counts, Signals,
and Synapses of the Counter device, as well as options and information
for the Counter device itself.
Thereafter, data can be transferred directly between the Counter device
driver and Counter userspace interface::
Each Signal has a directory created to house its relevant sysfs
attributes, where Y is the unique ID of the respective Signal:
Count data request:
~~~~~~~~~~~~~~~~~~~
----------------------
/ Counter device \
+----------------------+
| Count register: 0x28 |
+----------------------+
|
-----------------
/ raw count data /
-----------------
|
V
+----------------------------+
| Counter device driver |
+----------------------------+
| Processes data from device |
|----------------------------|
| Type: u64 |
| Value: 42 |
+----------------------------+
|
----------
/ u64 /
----------
|
+---------------+
|
V
+--------------------+
| Counter sysfs |
+--------------------+
| Translates to the |
| standard Counter |
| sysfs output |
|--------------------|
| Type: const char * |
| Value: "42" |
+--------------------+
|
---------------
/ const char * /
---------------
|
V
+--------------------------------------------------+
| `/sys/bus/counter/devices/counterX/countY/count` |
+--------------------------------------------------+
\ Count: "42" /
--------------------------------------------------
/sys/bus/counter/devices/counterX/signalY
There are three primary components involved:
Similarly, each Count has a directory created to house its relevant
sysfs attributes, where Y is the unique ID of the respective Count:
Counter device driver
---------------------
Communicates with the hardware device to read/write data; e.g. counter
drivers for quadrature encoders, timers, etc.
/sys/bus/counter/devices/counterX/countY
Counter core
------------
Registers the counter device driver to the system so that the respective
callbacks are called during userspace interaction.
For a more detailed breakdown of the available Generic Counter interface
sysfs attributes, please refer to the
Documentation/ABI/testing/sysfs-bus-counter file.
Counter sysfs
-------------
Translates counter data to the standard Counter sysfs interface format
and vice versa.
The Signals and Counts associated with the Counter device are registered
to the system as well by the counter_register function. The
signal_read/signal_write driver callbacks are associated with their
respective Signal attributes, while the count_read/count_write and
function_get/function_set driver callbacks are associated with their
respective Count attributes; similarly, the same is true for the
action_get/action_set driver callbacks and their respective Synapse
attributes. If a driver callback is left undefined, then the respective
read/write permission is left disabled for the relevant attributes.
Similarly, extension sysfs attributes are created for the defined
counter_device_ext, counter_count_ext, and counter_signal_ext
structures that are passed in.
Please refer to the ``Documentation/ABI/testing/sysfs-bus-counter`` file
for a detailed breakdown of the available Generic Counter interface
sysfs attributes.