Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'counter-for-5.16a-take2' of https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into char-misc-next

Jonathan writes:

First set of counter subsystem new feature support for the 5.16 cycle

Most interesting element this time is the new chrdev based interface
for the counter subsystem. Affects all drivers. Some minor precursor
patches.

Major parts:
* Bring all the sysfs attribute setup into the counter core rather than
leaving it to individual drivers. Docs updates accompany these changes.
* Move various definitions to a uapi header as now needed from userspace.
* Add the chardev interface + extensive documentation and example tool
* Add new ABI needed to identify indexes needed for chrdev interface
* Implement new interface for the 104-quad-8
* Follow up deals with wrong path for documentation build
* Various trivial cleanups and missing feature additions related to this
series

* tag 'counter-for-5.16a-take2' of https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio:
docs: counter: Include counter-chrdev kernel-doc to generic-counter.rst
counter: fix docum. build problems after filename change
counter: microchip-tcb-capture: Tidy up a false kernel-doc /** marking.
counter: 104-quad-8: Add IRQ support for the ACCES 104-QUAD-8
counter: 104-quad-8: Replace mutex with spinlock
counter: Implement events_queue_size sysfs attribute
counter: Implement *_component_id sysfs attributes
counter: Implement signalZ_action_component_id sysfs attribute
tools/counter: Create Counter tools
docs: counter: Document character device interface
counter: Add character device interface
counter: Move counter enums to uapi header
docs: counter: Update to reflect sysfs internalization
counter: Update counter.h comments to reflect sysfs internalization
counter: Internalize sysfs interface code
counter: stm32-timer-cnt: Provide defines for slave mode selection
counter: stm32-lptimer-cnt: Provide defines for clock polarities

+3595 -2785
+37 -1
Documentation/ABI/testing/sysfs-bus-counter
··· 203 203 both edges: 204 204 Any state transition. 205 205 206 + What: /sys/bus/counter/devices/counterX/countY/ceiling_component_id 207 + What: /sys/bus/counter/devices/counterX/countY/floor_component_id 208 + What: /sys/bus/counter/devices/counterX/countY/count_mode_component_id 209 + What: /sys/bus/counter/devices/counterX/countY/direction_component_id 210 + What: /sys/bus/counter/devices/counterX/countY/enable_component_id 211 + What: /sys/bus/counter/devices/counterX/countY/error_noise_component_id 212 + What: /sys/bus/counter/devices/counterX/countY/prescaler_component_id 213 + What: /sys/bus/counter/devices/counterX/countY/preset_component_id 214 + What: /sys/bus/counter/devices/counterX/countY/preset_enable_component_id 215 + What: /sys/bus/counter/devices/counterX/countY/signalZ_action_component_id 216 + What: /sys/bus/counter/devices/counterX/signalY/cable_fault_component_id 217 + What: /sys/bus/counter/devices/counterX/signalY/cable_fault_enable_component_id 218 + What: /sys/bus/counter/devices/counterX/signalY/filter_clock_prescaler_component_id 219 + What: /sys/bus/counter/devices/counterX/signalY/index_polarity_component_id 220 + What: /sys/bus/counter/devices/counterX/signalY/synchronous_mode_component_id 221 + KernelVersion: 5.16 222 + Contact: linux-iio@vger.kernel.org 223 + Description: 224 + Read-only attribute that indicates the component ID of the 225 + respective extension or Synapse. 226 + 206 227 What: /sys/bus/counter/devices/counterX/countY/spike_filter_ns 207 228 KernelVersion: 5.14 208 229 Contact: linux-iio@vger.kernel.org ··· 232 211 attribute indicates the value in nanoseconds where noise pulses 233 212 shorter or equal to configured value are ignored. Value 0 means 234 213 filter is disabled. 214 + 215 + What: /sys/bus/counter/devices/counterX/events_queue_size 216 + KernelVersion: 5.16 217 + Contact: linux-iio@vger.kernel.org 218 + Description: 219 + Size of the Counter events queue in number of struct 220 + counter_event data structures. The number of elements will be 221 + rounded-up to a power of 2. 235 222 236 223 What: /sys/bus/counter/devices/counterX/name 237 224 KernelVersion: 5.2 ··· 315 286 KernelVersion: 5.2 316 287 Contact: linux-iio@vger.kernel.org 317 288 Description: 318 - Signal data of Signal Y represented as a string. 289 + Signal level state of Signal Y. The following signal level 290 + states are available: 291 + 292 + low: 293 + Low level state. 294 + 295 + high: 296 + High level state. 319 297 320 298 What: /sys/bus/counter/devices/counterX/signalY/synchronous_mode 321 299 KernelVersion: 5.2
+277 -68
Documentation/driver-api/generic-counter.rst
··· 223 223 on the core idea of what the data and process represent (e.g. position 224 224 as interpreted from quadrature encoding data). 225 225 226 - Userspace Interface 227 - =================== 228 - 229 - Several sysfs attributes are generated by the Generic Counter interface, 230 - and reside under the /sys/bus/counter/devices/counterX directory, where 231 - counterX refers to the respective counter device. Please see 232 - Documentation/ABI/testing/sysfs-bus-counter for detailed 233 - information on each Generic Counter interface sysfs attribute. 234 - 235 - Through these sysfs attributes, programs and scripts may interact with 236 - the Generic Counter paradigm Counts, Signals, and Synapses of respective 237 - counter devices. 238 - 239 226 Driver API 240 227 ========== 241 228 ··· 234 247 .. kernel-doc:: include/linux/counter.h 235 248 :internal: 236 249 237 - .. kernel-doc:: drivers/counter/counter.c 250 + .. kernel-doc:: drivers/counter/counter-core.c 238 251 :export: 239 252 240 - Implementation 241 - ============== 253 + .. kernel-doc:: drivers/counter/counter-chrdev.c 254 + :export: 255 + 256 + Driver Implementation 257 + ===================== 242 258 243 259 To support a counter device, a driver must first allocate the available 244 260 Counter Signals via counter_signal structures. These Signals should ··· 257 267 set to the counts array member of an allocated counter_device structure 258 268 before the Counter is registered to the system. 259 269 260 - Driver callbacks should be provided to the counter_device structure via 261 - a constant counter_ops structure in order to communicate with the 262 - device: to read and write various Signals and Counts, and to set and get 263 - the "action mode" and "function mode" for various Synapses and Counts 264 - respectively. 270 + Driver callbacks must be provided to the counter_device structure in 271 + order to communicate with the device: to read and write various Signals 272 + and Counts, and to set and get the "action mode" and "function mode" for 273 + various Synapses and Counts respectively. 265 274 266 275 A defined counter_device structure may be registered to the system by 267 276 passing it to the counter_register function, and unregistered by passing 268 277 it to the counter_unregister function. Similarly, the 269 - devm_counter_register and devm_counter_unregister functions may be used 270 - if device memory-managed registration is desired. 278 + devm_counter_register function may be used if device memory-managed 279 + registration is desired. 271 280 272 - Extension sysfs attributes can be created for auxiliary functionality 273 - and data by passing in defined counter_device_ext, counter_count_ext, 274 - and counter_signal_ext structures. In these cases, the 275 - counter_device_ext structure is used for global/miscellaneous exposure 276 - and configuration of the respective Counter device, while the 277 - counter_count_ext and counter_signal_ext structures allow for auxiliary 278 - exposure and configuration of a specific Count or Signal respectively. 281 + The struct counter_comp structure is used to define counter extensions 282 + for Signals, Synapses, and Counts. 283 + 284 + The "type" member specifies the type of high-level data (e.g. BOOL, 285 + COUNT_DIRECTION, etc.) handled by this extension. The "``*_read``" and 286 + "``*_write``" members can then be set by the counter device driver with 287 + callbacks to handle that data using native C data types (i.e. u8, u64, 288 + etc.). 289 + 290 + Convenience macros such as ``COUNTER_COMP_COUNT_U64`` are provided for 291 + use by driver authors. In particular, driver authors are expected to use 292 + the provided macros for standard Counter subsystem attributes in order 293 + to maintain a consistent interface for userspace. For example, a counter 294 + device driver may define several standard attributes like so:: 295 + 296 + struct counter_comp count_ext[] = { 297 + COUNTER_COMP_DIRECTION(count_direction_read), 298 + COUNTER_COMP_ENABLE(count_enable_read, count_enable_write), 299 + COUNTER_COMP_CEILING(count_ceiling_read, count_ceiling_write), 300 + }; 301 + 302 + This makes it simple to see, add, and modify the attributes that are 303 + supported by this driver ("direction", "enable", and "ceiling") and to 304 + maintain this code without getting lost in a web of struct braces. 305 + 306 + Callbacks must match the function type expected for the respective 307 + component or extension. These function types are defined in the struct 308 + counter_comp structure as the "``*_read``" and "``*_write``" union 309 + members. 310 + 311 + The corresponding callback prototypes for the extensions mentioned in 312 + the previous example above would be:: 313 + 314 + int count_direction_read(struct counter_device *counter, 315 + struct counter_count *count, 316 + enum counter_count_direction *direction); 317 + int count_enable_read(struct counter_device *counter, 318 + struct counter_count *count, u8 *enable); 319 + int count_enable_write(struct counter_device *counter, 320 + struct counter_count *count, u8 enable); 321 + int count_ceiling_read(struct counter_device *counter, 322 + struct counter_count *count, u64 *ceiling); 323 + int count_ceiling_write(struct counter_device *counter, 324 + struct counter_count *count, u64 ceiling); 279 325 280 326 Determining the type of extension to create is a matter of scope. 281 327 ··· 339 313 chip overheated via a device extension called "error_overtemp": 340 314 /sys/bus/counter/devices/counterX/error_overtemp 341 315 342 - Architecture 343 - ============ 316 + Subsystem Architecture 317 + ====================== 344 318 345 - When the Generic Counter interface counter module is loaded, the 346 - counter_init function is called which registers a bus_type named 347 - "counter" to the system. Subsequently, when the module is unloaded, the 348 - counter_exit function is called which unregisters the bus_type named 349 - "counter" from the system. 319 + Counter drivers pass and take data natively (i.e. ``u8``, ``u64``, etc.) 320 + and the shared counter module handles the translation between the sysfs 321 + interface. This guarantees a standard userspace interface for all 322 + counter drivers, and enables a Generic Counter chrdev interface via a 323 + generalized device driver ABI. 350 324 351 - Counter devices are registered to the system via the counter_register 352 - function, and later removed via the counter_unregister function. The 353 - counter_register function establishes a unique ID for the Counter 354 - device and creates a respective sysfs directory, where X is the 355 - mentioned unique ID: 325 + A high-level view of how a count value is passed down from a counter 326 + driver is exemplified by the following. The driver callbacks are first 327 + registered to the Counter core component for use by the Counter 328 + userspace interface components:: 356 329 357 - /sys/bus/counter/devices/counterX 330 + Driver callbacks registration: 331 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 332 + +----------------------------+ 333 + | Counter device driver | 334 + +----------------------------+ 335 + | Processes data from device | 336 + +----------------------------+ 337 + | 338 + ------------------- 339 + / driver callbacks / 340 + ------------------- 341 + | 342 + V 343 + +----------------------+ 344 + | Counter core | 345 + +----------------------+ 346 + | Routes device driver | 347 + | callbacks to the | 348 + | userspace interfaces | 349 + +----------------------+ 350 + | 351 + ------------------- 352 + / driver callbacks / 353 + ------------------- 354 + | 355 + +---------------+---------------+ 356 + | | 357 + V V 358 + +--------------------+ +---------------------+ 359 + | Counter sysfs | | Counter chrdev | 360 + +--------------------+ +---------------------+ 361 + | Translates to the | | Translates to the | 362 + | standard Counter | | standard Counter | 363 + | sysfs output | | character device | 364 + +--------------------+ +---------------------+ 358 365 359 - Sysfs attributes are created within the counterX directory to expose 360 - functionality, configurations, and data relating to the Counts, Signals, 361 - and Synapses of the Counter device, as well as options and information 362 - for the Counter device itself. 366 + Thereafter, data can be transferred directly between the Counter device 367 + driver and Counter userspace interface:: 363 368 364 - Each Signal has a directory created to house its relevant sysfs 365 - attributes, where Y is the unique ID of the respective Signal: 369 + Count data request: 370 + ~~~~~~~~~~~~~~~~~~~ 371 + ---------------------- 372 + / Counter device \ 373 + +----------------------+ 374 + | Count register: 0x28 | 375 + +----------------------+ 376 + | 377 + ----------------- 378 + / raw count data / 379 + ----------------- 380 + | 381 + V 382 + +----------------------------+ 383 + | Counter device driver | 384 + +----------------------------+ 385 + | Processes data from device | 386 + |----------------------------| 387 + | Type: u64 | 388 + | Value: 42 | 389 + +----------------------------+ 390 + | 391 + ---------- 392 + / u64 / 393 + ---------- 394 + | 395 + +---------------+---------------+ 396 + | | 397 + V V 398 + +--------------------+ +---------------------+ 399 + | Counter sysfs | | Counter chrdev | 400 + +--------------------+ +---------------------+ 401 + | Translates to the | | Translates to the | 402 + | standard Counter | | standard Counter | 403 + | sysfs output | | character device | 404 + |--------------------| |---------------------| 405 + | Type: const char * | | Type: u64 | 406 + | Value: "42" | | Value: 42 | 407 + +--------------------+ +---------------------+ 408 + | | 409 + --------------- ----------------------- 410 + / const char * / / struct counter_event / 411 + --------------- ----------------------- 412 + | | 413 + | V 414 + | +-----------+ 415 + | | read | 416 + | +-----------+ 417 + | \ Count: 42 / 418 + | ----------- 419 + | 420 + V 421 + +--------------------------------------------------+ 422 + | `/sys/bus/counter/devices/counterX/countY/count` | 423 + +--------------------------------------------------+ 424 + \ Count: "42" / 425 + -------------------------------------------------- 366 426 367 - /sys/bus/counter/devices/counterX/signalY 427 + There are four primary components involved: 368 428 369 - Similarly, each Count has a directory created to house its relevant 370 - sysfs attributes, where Y is the unique ID of the respective Count: 429 + Counter device driver 430 + --------------------- 431 + Communicates with the hardware device to read/write data; e.g. counter 432 + drivers for quadrature encoders, timers, etc. 371 433 372 - /sys/bus/counter/devices/counterX/countY 434 + Counter core 435 + ------------ 436 + Registers the counter device driver to the system so that the respective 437 + callbacks are called during userspace interaction. 373 438 374 - For a more detailed breakdown of the available Generic Counter interface 375 - sysfs attributes, please refer to the 376 - Documentation/ABI/testing/sysfs-bus-counter file. 439 + Counter sysfs 440 + ------------- 441 + Translates counter data to the standard Counter sysfs interface format 442 + and vice versa. 377 443 378 - The Signals and Counts associated with the Counter device are registered 379 - to the system as well by the counter_register function. The 380 - signal_read/signal_write driver callbacks are associated with their 381 - respective Signal attributes, while the count_read/count_write and 382 - function_get/function_set driver callbacks are associated with their 383 - respective Count attributes; similarly, the same is true for the 384 - action_get/action_set driver callbacks and their respective Synapse 385 - attributes. If a driver callback is left undefined, then the respective 386 - read/write permission is left disabled for the relevant attributes. 444 + Please refer to the ``Documentation/ABI/testing/sysfs-bus-counter`` file 445 + for a detailed breakdown of the available Generic Counter interface 446 + sysfs attributes. 387 447 388 - Similarly, extension sysfs attributes are created for the defined 389 - counter_device_ext, counter_count_ext, and counter_signal_ext 390 - structures that are passed in. 448 + Counter chrdev 449 + -------------- 450 + Translates Counter events to the standard Counter character device; data 451 + is transferred via standard character device read calls, while Counter 452 + events are configured via ioctl calls. 453 + 454 + Sysfs Interface 455 + =============== 456 + 457 + Several sysfs attributes are generated by the Generic Counter interface, 458 + and reside under the ``/sys/bus/counter/devices/counterX`` directory, 459 + where ``X`` is to the respective counter device id. Please see 460 + ``Documentation/ABI/testing/sysfs-bus-counter`` for detailed information 461 + on each Generic Counter interface sysfs attribute. 462 + 463 + Through these sysfs attributes, programs and scripts may interact with 464 + the Generic Counter paradigm Counts, Signals, and Synapses of respective 465 + counter devices. 466 + 467 + Counter Character Device 468 + ======================== 469 + 470 + Counter character device nodes are created under the ``/dev`` directory 471 + as ``counterX``, where ``X`` is the respective counter device id. 472 + Defines for the standard Counter data types are exposed via the 473 + userspace ``include/uapi/linux/counter.h`` file. 474 + 475 + Counter events 476 + -------------- 477 + Counter device drivers can support Counter events by utilizing the 478 + ``counter_push_event`` function:: 479 + 480 + void counter_push_event(struct counter_device *const counter, const u8 event, 481 + const u8 channel); 482 + 483 + The event id is specified by the ``event`` parameter; the event channel 484 + id is specified by the ``channel`` parameter. When this function is 485 + called, the Counter data associated with the respective event is 486 + gathered, and a ``struct counter_event`` is generated for each datum and 487 + pushed to userspace. 488 + 489 + Counter events can be configured by users to report various Counter 490 + data of interest. This can be conceptualized as a list of Counter 491 + component read calls to perform. For example: 492 + 493 + +------------------------+------------------------+ 494 + | COUNTER_EVENT_OVERFLOW | COUNTER_EVENT_INDEX | 495 + +========================+========================+ 496 + | Channel 0 | Channel 0 | 497 + +------------------------+------------------------+ 498 + | * Count 0 | * Signal 0 | 499 + | * Count 1 | * Signal 0 Extension 0 | 500 + | * Signal 3 | * Extension 4 | 501 + | * Count 4 Extension 2 +------------------------+ 502 + | * Signal 5 Extension 0 | Channel 1 | 503 + | +------------------------+ 504 + | | * Signal 4 | 505 + | | * Signal 4 Extension 0 | 506 + | | * Count 7 | 507 + +------------------------+------------------------+ 508 + 509 + When ``counter_push_event(counter, COUNTER_EVENT_INDEX, 1)`` is called 510 + for example, it will go down the list for the ``COUNTER_EVENT_INDEX`` 511 + event channel 1 and execute the read callbacks for Signal 4, Signal 4 512 + Extension 0, and Count 7 -- the data returned for each is pushed to a 513 + kfifo as a ``struct counter_event``, which userspace can retrieve via a 514 + standard read operation on the respective character device node. 515 + 516 + Userspace 517 + --------- 518 + Userspace applications can configure Counter events via ioctl operations 519 + on the Counter character device node. There following ioctl codes are 520 + supported and provided by the ``linux/counter.h`` userspace header file: 521 + 522 + * :c:macro:`COUNTER_ADD_WATCH_IOCTL` 523 + 524 + * :c:macro:`COUNTER_ENABLE_EVENTS_IOCTL` 525 + 526 + * :c:macro:`COUNTER_DISABLE_EVENTS_IOCTL` 527 + 528 + To configure events to gather Counter data, users first populate a 529 + ``struct counter_watch`` with the relevant event id, event channel id, 530 + and the information for the desired Counter component from which to 531 + read, and then pass it via the ``COUNTER_ADD_WATCH_IOCTL`` ioctl 532 + command. 533 + 534 + Note that an event can be watched without gathering Counter data by 535 + setting the ``component.type`` member equal to 536 + ``COUNTER_COMPONENT_NONE``. With this configuration the Counter 537 + character device will simply populate the event timestamps for those 538 + respective ``struct counter_event`` elements and ignore the component 539 + value. 540 + 541 + The ``COUNTER_ADD_WATCH_IOCTL`` command will buffer these Counter 542 + watches. When ready, the ``COUNTER_ENABLE_EVENTS_IOCTL`` ioctl command 543 + may be used to activate these Counter watches. 544 + 545 + Userspace applications can then execute a ``read`` operation (optionally 546 + calling ``poll`` first) on the Counter character device node to retrieve 547 + ``struct counter_event`` elements with the desired data.
+1
Documentation/userspace-api/ioctl/ioctl-number.rst
··· 88 88 <http://infiniband.sourceforge.net/> 89 89 0x20 all drivers/cdrom/cm206.h 90 90 0x22 all scsi/sg.h 91 + 0x3E 00-0F linux/counter.h <mailto:linux-iio@vger.kernel.org> 91 92 '!' 00-1F uapi/linux/seccomp.h 92 93 '#' 00-3F IEEE 1394 Subsystem 93 94 Block for the entire subsystem
+2 -1
MAINTAINERS
··· 4810 4810 F: Documentation/driver-api/generic-counter.rst 4811 4811 F: drivers/counter/ 4812 4812 F: include/linux/counter.h 4813 - F: include/linux/counter_enum.h 4813 + F: include/uapi/linux/counter.h 4814 + F: tools/counter/ 4814 4815 4815 4816 CP2615 I2C DRIVER 4816 4817 M: Bence Csókás <bence98@sch.bme.hu>
+401 -298
drivers/counter/104-quad-8.c
··· 11 11 #include <linux/errno.h> 12 12 #include <linux/io.h> 13 13 #include <linux/ioport.h> 14 + #include <linux/interrupt.h> 14 15 #include <linux/isa.h> 15 16 #include <linux/kernel.h> 16 17 #include <linux/module.h> 17 18 #include <linux/moduleparam.h> 18 19 #include <linux/types.h> 20 + #include <linux/spinlock.h> 19 21 20 22 #define QUAD8_EXTENT 32 21 23 ··· 25 23 static unsigned int num_quad8; 26 24 module_param_hw_array(base, uint, ioport, &num_quad8, 0); 27 25 MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses"); 26 + 27 + static unsigned int irq[max_num_isa_dev(QUAD8_EXTENT)]; 28 + module_param_hw_array(irq, uint, irq, NULL, 0); 29 + MODULE_PARM_DESC(irq, "ACCES 104-QUAD-8 interrupt line numbers"); 28 30 29 31 #define QUAD8_NUM_COUNTERS 8 30 32 ··· 43 37 * @quadrature_scale: array of quadrature mode scale configurations 44 38 * @ab_enable: array of A and B inputs enable configurations 45 39 * @preset_enable: array of set_to_preset_on_index attribute configurations 40 + * @irq_trigger: array of current IRQ trigger function configurations 41 + * @next_irq_trigger: array of next IRQ trigger function configurations 46 42 * @synchronous_mode: array of index function synchronous mode configurations 47 43 * @index_polarity: array of index function polarity configurations 48 44 * @cable_fault_enable: differential encoder cable status enable configurations 49 45 * @base: base port address of the device 50 46 */ 51 47 struct quad8 { 52 - struct mutex lock; 48 + spinlock_t lock; 53 49 struct counter_device counter; 54 50 unsigned int fck_prescaler[QUAD8_NUM_COUNTERS]; 55 51 unsigned int preset[QUAD8_NUM_COUNTERS]; ··· 60 52 unsigned int quadrature_scale[QUAD8_NUM_COUNTERS]; 61 53 unsigned int ab_enable[QUAD8_NUM_COUNTERS]; 62 54 unsigned int preset_enable[QUAD8_NUM_COUNTERS]; 55 + unsigned int irq_trigger[QUAD8_NUM_COUNTERS]; 56 + unsigned int next_irq_trigger[QUAD8_NUM_COUNTERS]; 63 57 unsigned int synchronous_mode[QUAD8_NUM_COUNTERS]; 64 58 unsigned int index_polarity[QUAD8_NUM_COUNTERS]; 65 59 unsigned int cable_fault_enable; 66 60 unsigned int base; 67 61 }; 68 62 63 + #define QUAD8_REG_INTERRUPT_STATUS 0x10 69 64 #define QUAD8_REG_CHAN_OP 0x11 65 + #define QUAD8_REG_INDEX_INTERRUPT 0x12 70 66 #define QUAD8_REG_INDEX_INPUT_LEVELS 0x16 71 67 #define QUAD8_DIFF_ENCODER_CABLE_STATUS 0x17 72 68 /* Borrow Toggle flip-flop */ ··· 103 91 #define QUAD8_RLD_CNTR_OUT 0x10 104 92 /* Transfer Preset Register LSB to FCK Prescaler */ 105 93 #define QUAD8_RLD_PRESET_PSC 0x18 106 - #define QUAD8_CHAN_OP_ENABLE_COUNTERS 0x00 107 94 #define QUAD8_CHAN_OP_RESET_COUNTERS 0x01 95 + #define QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC 0x04 108 96 #define QUAD8_CMR_QUADRATURE_X1 0x08 109 97 #define QUAD8_CMR_QUADRATURE_X2 0x10 110 98 #define QUAD8_CMR_QUADRATURE_X4 0x18 ··· 129 117 } 130 118 131 119 static int quad8_count_read(struct counter_device *counter, 132 - struct counter_count *count, unsigned long *val) 120 + struct counter_count *count, u64 *val) 133 121 { 134 122 struct quad8 *const priv = counter->priv; 135 123 const int base_offset = priv->base + 2 * count->id; 136 124 unsigned int flags; 137 125 unsigned int borrow; 138 126 unsigned int carry; 127 + unsigned long irqflags; 139 128 int i; 140 129 141 130 flags = inb(base_offset + 1); ··· 146 133 /* Borrow XOR Carry effectively doubles count range */ 147 134 *val = (unsigned long)(borrow ^ carry) << 24; 148 135 149 - mutex_lock(&priv->lock); 136 + spin_lock_irqsave(&priv->lock, irqflags); 150 137 151 138 /* Reset Byte Pointer; transfer Counter to Output Latch */ 152 139 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT, ··· 155 142 for (i = 0; i < 3; i++) 156 143 *val |= (unsigned long)inb(base_offset) << (8 * i); 157 144 158 - mutex_unlock(&priv->lock); 145 + spin_unlock_irqrestore(&priv->lock, irqflags); 159 146 160 147 return 0; 161 148 } 162 149 163 150 static int quad8_count_write(struct counter_device *counter, 164 - struct counter_count *count, unsigned long val) 151 + struct counter_count *count, u64 val) 165 152 { 166 153 struct quad8 *const priv = counter->priv; 167 154 const int base_offset = priv->base + 2 * count->id; 155 + unsigned long irqflags; 168 156 int i; 169 157 170 158 /* Only 24-bit values are supported */ 171 159 if (val > 0xFFFFFF) 172 160 return -ERANGE; 173 161 174 - mutex_lock(&priv->lock); 162 + spin_lock_irqsave(&priv->lock, irqflags); 175 163 176 164 /* Reset Byte Pointer */ 177 165 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); ··· 197 183 /* Reset Error flag */ 198 184 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1); 199 185 200 - mutex_unlock(&priv->lock); 186 + spin_unlock_irqrestore(&priv->lock, irqflags); 201 187 202 188 return 0; 203 189 } 204 190 205 - enum quad8_count_function { 206 - QUAD8_COUNT_FUNCTION_PULSE_DIRECTION = 0, 207 - QUAD8_COUNT_FUNCTION_QUADRATURE_X1, 208 - QUAD8_COUNT_FUNCTION_QUADRATURE_X2, 209 - QUAD8_COUNT_FUNCTION_QUADRATURE_X4 210 - }; 211 - 212 191 static const enum counter_function quad8_count_functions_list[] = { 213 - [QUAD8_COUNT_FUNCTION_PULSE_DIRECTION] = COUNTER_FUNCTION_PULSE_DIRECTION, 214 - [QUAD8_COUNT_FUNCTION_QUADRATURE_X1] = COUNTER_FUNCTION_QUADRATURE_X1_A, 215 - [QUAD8_COUNT_FUNCTION_QUADRATURE_X2] = COUNTER_FUNCTION_QUADRATURE_X2_A, 216 - [QUAD8_COUNT_FUNCTION_QUADRATURE_X4] = COUNTER_FUNCTION_QUADRATURE_X4 192 + COUNTER_FUNCTION_PULSE_DIRECTION, 193 + COUNTER_FUNCTION_QUADRATURE_X1_A, 194 + COUNTER_FUNCTION_QUADRATURE_X2_A, 195 + COUNTER_FUNCTION_QUADRATURE_X4, 217 196 }; 218 197 219 - static int quad8_function_get(struct counter_device *counter, 220 - struct counter_count *count, size_t *function) 198 + static int quad8_function_read(struct counter_device *counter, 199 + struct counter_count *count, 200 + enum counter_function *function) 221 201 { 222 202 struct quad8 *const priv = counter->priv; 223 203 const int id = count->id; 204 + unsigned long irqflags; 224 205 225 - mutex_lock(&priv->lock); 206 + spin_lock_irqsave(&priv->lock, irqflags); 226 207 227 208 if (priv->quadrature_mode[id]) 228 209 switch (priv->quadrature_scale[id]) { 229 210 case 0: 230 - *function = QUAD8_COUNT_FUNCTION_QUADRATURE_X1; 211 + *function = COUNTER_FUNCTION_QUADRATURE_X1_A; 231 212 break; 232 213 case 1: 233 - *function = QUAD8_COUNT_FUNCTION_QUADRATURE_X2; 214 + *function = COUNTER_FUNCTION_QUADRATURE_X2_A; 234 215 break; 235 216 case 2: 236 - *function = QUAD8_COUNT_FUNCTION_QUADRATURE_X4; 217 + *function = COUNTER_FUNCTION_QUADRATURE_X4; 237 218 break; 238 219 } 239 220 else 240 - *function = QUAD8_COUNT_FUNCTION_PULSE_DIRECTION; 221 + *function = COUNTER_FUNCTION_PULSE_DIRECTION; 241 222 242 - mutex_unlock(&priv->lock); 223 + spin_unlock_irqrestore(&priv->lock, irqflags); 243 224 244 225 return 0; 245 226 } 246 227 247 - static int quad8_function_set(struct counter_device *counter, 248 - struct counter_count *count, size_t function) 228 + static int quad8_function_write(struct counter_device *counter, 229 + struct counter_count *count, 230 + enum counter_function function) 249 231 { 250 232 struct quad8 *const priv = counter->priv; 251 233 const int id = count->id; ··· 249 239 unsigned int *const scale = priv->quadrature_scale + id; 250 240 unsigned int *const synchronous_mode = priv->synchronous_mode + id; 251 241 const int base_offset = priv->base + 2 * id + 1; 242 + unsigned long irqflags; 252 243 unsigned int mode_cfg; 253 244 unsigned int idr_cfg; 254 245 255 - mutex_lock(&priv->lock); 246 + spin_lock_irqsave(&priv->lock, irqflags); 256 247 257 248 mode_cfg = priv->count_mode[id] << 1; 258 249 idr_cfg = priv->index_polarity[id] << 1; 259 250 260 - if (function == QUAD8_COUNT_FUNCTION_PULSE_DIRECTION) { 251 + if (function == COUNTER_FUNCTION_PULSE_DIRECTION) { 261 252 *quadrature_mode = 0; 262 253 263 254 /* Quadrature scaling only available in quadrature mode */ ··· 274 263 *quadrature_mode = 1; 275 264 276 265 switch (function) { 277 - case QUAD8_COUNT_FUNCTION_QUADRATURE_X1: 266 + case COUNTER_FUNCTION_QUADRATURE_X1_A: 278 267 *scale = 0; 279 268 mode_cfg |= QUAD8_CMR_QUADRATURE_X1; 280 269 break; 281 - case QUAD8_COUNT_FUNCTION_QUADRATURE_X2: 270 + case COUNTER_FUNCTION_QUADRATURE_X2_A: 282 271 *scale = 1; 283 272 mode_cfg |= QUAD8_CMR_QUADRATURE_X2; 284 273 break; 285 - case QUAD8_COUNT_FUNCTION_QUADRATURE_X4: 274 + case COUNTER_FUNCTION_QUADRATURE_X4: 286 275 *scale = 2; 287 276 mode_cfg |= QUAD8_CMR_QUADRATURE_X4; 288 277 break; 289 278 default: 290 279 /* should never reach this path */ 291 - mutex_unlock(&priv->lock); 280 + spin_unlock_irqrestore(&priv->lock, irqflags); 292 281 return -EINVAL; 293 282 } 294 283 } ··· 296 285 /* Load mode configuration to Counter Mode Register */ 297 286 outb(QUAD8_CTR_CMR | mode_cfg, base_offset); 298 287 299 - mutex_unlock(&priv->lock); 288 + spin_unlock_irqrestore(&priv->lock, irqflags); 300 289 301 290 return 0; 302 291 } 303 292 304 - static void quad8_direction_get(struct counter_device *counter, 305 - struct counter_count *count, enum counter_count_direction *direction) 293 + static int quad8_direction_read(struct counter_device *counter, 294 + struct counter_count *count, 295 + enum counter_count_direction *direction) 306 296 { 307 297 const struct quad8 *const priv = counter->priv; 308 298 unsigned int ud_flag; ··· 314 302 315 303 *direction = (ud_flag) ? COUNTER_COUNT_DIRECTION_FORWARD : 316 304 COUNTER_COUNT_DIRECTION_BACKWARD; 305 + 306 + return 0; 317 307 } 318 308 319 - enum quad8_synapse_action { 320 - QUAD8_SYNAPSE_ACTION_NONE = 0, 321 - QUAD8_SYNAPSE_ACTION_RISING_EDGE, 322 - QUAD8_SYNAPSE_ACTION_FALLING_EDGE, 323 - QUAD8_SYNAPSE_ACTION_BOTH_EDGES 324 - }; 325 - 326 309 static const enum counter_synapse_action quad8_index_actions_list[] = { 327 - [QUAD8_SYNAPSE_ACTION_NONE] = COUNTER_SYNAPSE_ACTION_NONE, 328 - [QUAD8_SYNAPSE_ACTION_RISING_EDGE] = COUNTER_SYNAPSE_ACTION_RISING_EDGE 310 + COUNTER_SYNAPSE_ACTION_NONE, 311 + COUNTER_SYNAPSE_ACTION_RISING_EDGE, 329 312 }; 330 313 331 314 static const enum counter_synapse_action quad8_synapse_actions_list[] = { 332 - [QUAD8_SYNAPSE_ACTION_NONE] = COUNTER_SYNAPSE_ACTION_NONE, 333 - [QUAD8_SYNAPSE_ACTION_RISING_EDGE] = COUNTER_SYNAPSE_ACTION_RISING_EDGE, 334 - [QUAD8_SYNAPSE_ACTION_FALLING_EDGE] = COUNTER_SYNAPSE_ACTION_FALLING_EDGE, 335 - [QUAD8_SYNAPSE_ACTION_BOTH_EDGES] = COUNTER_SYNAPSE_ACTION_BOTH_EDGES 315 + COUNTER_SYNAPSE_ACTION_NONE, 316 + COUNTER_SYNAPSE_ACTION_RISING_EDGE, 317 + COUNTER_SYNAPSE_ACTION_FALLING_EDGE, 318 + COUNTER_SYNAPSE_ACTION_BOTH_EDGES, 336 319 }; 337 320 338 - static int quad8_action_get(struct counter_device *counter, 339 - struct counter_count *count, struct counter_synapse *synapse, 340 - size_t *action) 321 + static int quad8_action_read(struct counter_device *counter, 322 + struct counter_count *count, 323 + struct counter_synapse *synapse, 324 + enum counter_synapse_action *action) 341 325 { 342 326 struct quad8 *const priv = counter->priv; 343 327 int err; 344 - size_t function = 0; 328 + enum counter_function function; 345 329 const size_t signal_a_id = count->synapses[0].signal->id; 346 330 enum counter_count_direction direction; 347 331 348 332 /* Handle Index signals */ 349 333 if (synapse->signal->id >= 16) { 350 334 if (priv->preset_enable[count->id]) 351 - *action = QUAD8_SYNAPSE_ACTION_RISING_EDGE; 335 + *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE; 352 336 else 353 - *action = QUAD8_SYNAPSE_ACTION_NONE; 337 + *action = COUNTER_SYNAPSE_ACTION_NONE; 354 338 355 339 return 0; 356 340 } 357 341 358 - err = quad8_function_get(counter, count, &function); 342 + err = quad8_function_read(counter, count, &function); 359 343 if (err) 360 344 return err; 361 345 362 346 /* Default action mode */ 363 - *action = QUAD8_SYNAPSE_ACTION_NONE; 347 + *action = COUNTER_SYNAPSE_ACTION_NONE; 364 348 365 349 /* Determine action mode based on current count function mode */ 366 350 switch (function) { 367 - case QUAD8_COUNT_FUNCTION_PULSE_DIRECTION: 351 + case COUNTER_FUNCTION_PULSE_DIRECTION: 368 352 if (synapse->signal->id == signal_a_id) 369 - *action = QUAD8_SYNAPSE_ACTION_RISING_EDGE; 353 + *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE; 370 354 return 0; 371 - case QUAD8_COUNT_FUNCTION_QUADRATURE_X1: 355 + case COUNTER_FUNCTION_QUADRATURE_X1_A: 372 356 if (synapse->signal->id == signal_a_id) { 373 - quad8_direction_get(counter, count, &direction); 357 + err = quad8_direction_read(counter, count, &direction); 358 + if (err) 359 + return err; 374 360 375 361 if (direction == COUNTER_COUNT_DIRECTION_FORWARD) 376 - *action = QUAD8_SYNAPSE_ACTION_RISING_EDGE; 362 + *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE; 377 363 else 378 - *action = QUAD8_SYNAPSE_ACTION_FALLING_EDGE; 364 + *action = COUNTER_SYNAPSE_ACTION_FALLING_EDGE; 379 365 } 380 366 return 0; 381 - case QUAD8_COUNT_FUNCTION_QUADRATURE_X2: 367 + case COUNTER_FUNCTION_QUADRATURE_X2_A: 382 368 if (synapse->signal->id == signal_a_id) 383 - *action = QUAD8_SYNAPSE_ACTION_BOTH_EDGES; 369 + *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES; 384 370 return 0; 385 - case QUAD8_COUNT_FUNCTION_QUADRATURE_X4: 386 - *action = QUAD8_SYNAPSE_ACTION_BOTH_EDGES; 371 + case COUNTER_FUNCTION_QUADRATURE_X4: 372 + *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES; 387 373 return 0; 388 374 default: 389 375 /* should never reach this path */ 376 + return -EINVAL; 377 + } 378 + } 379 + 380 + enum { 381 + QUAD8_EVENT_NONE = -1, 382 + QUAD8_EVENT_CARRY = 0, 383 + QUAD8_EVENT_COMPARE = 1, 384 + QUAD8_EVENT_CARRY_BORROW = 2, 385 + QUAD8_EVENT_INDEX = 3, 386 + }; 387 + 388 + static int quad8_events_configure(struct counter_device *counter) 389 + { 390 + struct quad8 *const priv = counter->priv; 391 + unsigned long irq_enabled = 0; 392 + unsigned long irqflags; 393 + size_t channel; 394 + unsigned long ior_cfg; 395 + unsigned long base_offset; 396 + 397 + spin_lock_irqsave(&priv->lock, irqflags); 398 + 399 + /* Enable interrupts for the requested channels, disable for the rest */ 400 + for (channel = 0; channel < QUAD8_NUM_COUNTERS; channel++) { 401 + if (priv->next_irq_trigger[channel] == QUAD8_EVENT_NONE) 402 + continue; 403 + 404 + if (priv->irq_trigger[channel] != priv->next_irq_trigger[channel]) { 405 + /* Save new IRQ function configuration */ 406 + priv->irq_trigger[channel] = priv->next_irq_trigger[channel]; 407 + 408 + /* Load configuration to I/O Control Register */ 409 + ior_cfg = priv->ab_enable[channel] | 410 + priv->preset_enable[channel] << 1 | 411 + priv->irq_trigger[channel] << 3; 412 + base_offset = priv->base + 2 * channel + 1; 413 + outb(QUAD8_CTR_IOR | ior_cfg, base_offset); 414 + } 415 + 416 + /* Reset next IRQ trigger function configuration */ 417 + priv->next_irq_trigger[channel] = QUAD8_EVENT_NONE; 418 + 419 + /* Enable IRQ line */ 420 + irq_enabled |= BIT(channel); 421 + } 422 + 423 + outb(irq_enabled, priv->base + QUAD8_REG_INDEX_INTERRUPT); 424 + 425 + spin_unlock_irqrestore(&priv->lock, irqflags); 426 + 427 + return 0; 428 + } 429 + 430 + static int quad8_watch_validate(struct counter_device *counter, 431 + const struct counter_watch *watch) 432 + { 433 + struct quad8 *const priv = counter->priv; 434 + 435 + if (watch->channel > QUAD8_NUM_COUNTERS - 1) 436 + return -EINVAL; 437 + 438 + switch (watch->event) { 439 + case COUNTER_EVENT_OVERFLOW: 440 + if (priv->next_irq_trigger[watch->channel] == QUAD8_EVENT_NONE) 441 + priv->next_irq_trigger[watch->channel] = QUAD8_EVENT_CARRY; 442 + else if (priv->next_irq_trigger[watch->channel] != QUAD8_EVENT_CARRY) 443 + return -EINVAL; 444 + return 0; 445 + case COUNTER_EVENT_THRESHOLD: 446 + if (priv->next_irq_trigger[watch->channel] == QUAD8_EVENT_NONE) 447 + priv->next_irq_trigger[watch->channel] = QUAD8_EVENT_COMPARE; 448 + else if (priv->next_irq_trigger[watch->channel] != QUAD8_EVENT_COMPARE) 449 + return -EINVAL; 450 + return 0; 451 + case COUNTER_EVENT_OVERFLOW_UNDERFLOW: 452 + if (priv->next_irq_trigger[watch->channel] == QUAD8_EVENT_NONE) 453 + priv->next_irq_trigger[watch->channel] = QUAD8_EVENT_CARRY_BORROW; 454 + else if (priv->next_irq_trigger[watch->channel] != QUAD8_EVENT_CARRY_BORROW) 455 + return -EINVAL; 456 + return 0; 457 + case COUNTER_EVENT_INDEX: 458 + if (priv->next_irq_trigger[watch->channel] == QUAD8_EVENT_NONE) 459 + priv->next_irq_trigger[watch->channel] = QUAD8_EVENT_INDEX; 460 + else if (priv->next_irq_trigger[watch->channel] != QUAD8_EVENT_INDEX) 461 + return -EINVAL; 462 + return 0; 463 + default: 390 464 return -EINVAL; 391 465 } 392 466 } ··· 481 383 .signal_read = quad8_signal_read, 482 384 .count_read = quad8_count_read, 483 385 .count_write = quad8_count_write, 484 - .function_get = quad8_function_get, 485 - .function_set = quad8_function_set, 486 - .action_get = quad8_action_get 386 + .function_read = quad8_function_read, 387 + .function_write = quad8_function_write, 388 + .action_read = quad8_action_read, 389 + .events_configure = quad8_events_configure, 390 + .watch_validate = quad8_watch_validate, 487 391 }; 488 392 489 393 static const char *const quad8_index_polarity_modes[] = { ··· 494 394 }; 495 395 496 396 static int quad8_index_polarity_get(struct counter_device *counter, 497 - struct counter_signal *signal, size_t *index_polarity) 397 + struct counter_signal *signal, 398 + u32 *index_polarity) 498 399 { 499 400 const struct quad8 *const priv = counter->priv; 500 401 const size_t channel_id = signal->id - 16; ··· 506 405 } 507 406 508 407 static int quad8_index_polarity_set(struct counter_device *counter, 509 - struct counter_signal *signal, size_t index_polarity) 408 + struct counter_signal *signal, 409 + u32 index_polarity) 510 410 { 511 411 struct quad8 *const priv = counter->priv; 512 412 const size_t channel_id = signal->id - 16; 513 413 const int base_offset = priv->base + 2 * channel_id + 1; 414 + unsigned long irqflags; 514 415 unsigned int idr_cfg = index_polarity << 1; 515 416 516 - mutex_lock(&priv->lock); 417 + spin_lock_irqsave(&priv->lock, irqflags); 517 418 518 419 idr_cfg |= priv->synchronous_mode[channel_id]; 519 420 ··· 524 421 /* Load Index Control configuration to Index Control Register */ 525 422 outb(QUAD8_CTR_IDR | idr_cfg, base_offset); 526 423 527 - mutex_unlock(&priv->lock); 424 + spin_unlock_irqrestore(&priv->lock, irqflags); 528 425 529 426 return 0; 530 427 } 531 - 532 - static struct counter_signal_enum_ext quad8_index_pol_enum = { 533 - .items = quad8_index_polarity_modes, 534 - .num_items = ARRAY_SIZE(quad8_index_polarity_modes), 535 - .get = quad8_index_polarity_get, 536 - .set = quad8_index_polarity_set 537 - }; 538 428 539 429 static const char *const quad8_synchronous_modes[] = { 540 430 "non-synchronous", ··· 535 439 }; 536 440 537 441 static int quad8_synchronous_mode_get(struct counter_device *counter, 538 - struct counter_signal *signal, size_t *synchronous_mode) 442 + struct counter_signal *signal, 443 + u32 *synchronous_mode) 539 444 { 540 445 const struct quad8 *const priv = counter->priv; 541 446 const size_t channel_id = signal->id - 16; ··· 547 450 } 548 451 549 452 static int quad8_synchronous_mode_set(struct counter_device *counter, 550 - struct counter_signal *signal, size_t synchronous_mode) 453 + struct counter_signal *signal, 454 + u32 synchronous_mode) 551 455 { 552 456 struct quad8 *const priv = counter->priv; 553 457 const size_t channel_id = signal->id - 16; 554 458 const int base_offset = priv->base + 2 * channel_id + 1; 459 + unsigned long irqflags; 555 460 unsigned int idr_cfg = synchronous_mode; 556 461 557 - mutex_lock(&priv->lock); 462 + spin_lock_irqsave(&priv->lock, irqflags); 558 463 559 464 idr_cfg |= priv->index_polarity[channel_id] << 1; 560 465 561 466 /* Index function must be non-synchronous in non-quadrature mode */ 562 467 if (synchronous_mode && !priv->quadrature_mode[channel_id]) { 563 - mutex_unlock(&priv->lock); 468 + spin_unlock_irqrestore(&priv->lock, irqflags); 564 469 return -EINVAL; 565 470 } 566 471 ··· 571 472 /* Load Index Control configuration to Index Control Register */ 572 473 outb(QUAD8_CTR_IDR | idr_cfg, base_offset); 573 474 574 - mutex_unlock(&priv->lock); 475 + spin_unlock_irqrestore(&priv->lock, irqflags); 575 476 576 477 return 0; 577 478 } 578 479 579 - static struct counter_signal_enum_ext quad8_syn_mode_enum = { 580 - .items = quad8_synchronous_modes, 581 - .num_items = ARRAY_SIZE(quad8_synchronous_modes), 582 - .get = quad8_synchronous_mode_get, 583 - .set = quad8_synchronous_mode_set 584 - }; 585 - 586 - static ssize_t quad8_count_floor_read(struct counter_device *counter, 587 - struct counter_count *count, void *private, char *buf) 480 + static int quad8_count_floor_read(struct counter_device *counter, 481 + struct counter_count *count, u64 *floor) 588 482 { 589 483 /* Only a floor of 0 is supported */ 590 - return sprintf(buf, "0\n"); 484 + *floor = 0; 485 + 486 + return 0; 591 487 } 592 488 593 - static int quad8_count_mode_get(struct counter_device *counter, 594 - struct counter_count *count, size_t *cnt_mode) 489 + static int quad8_count_mode_read(struct counter_device *counter, 490 + struct counter_count *count, 491 + enum counter_count_mode *cnt_mode) 595 492 { 596 493 const struct quad8 *const priv = counter->priv; 597 494 ··· 610 515 return 0; 611 516 } 612 517 613 - static int quad8_count_mode_set(struct counter_device *counter, 614 - struct counter_count *count, size_t cnt_mode) 518 + static int quad8_count_mode_write(struct counter_device *counter, 519 + struct counter_count *count, 520 + enum counter_count_mode cnt_mode) 615 521 { 616 522 struct quad8 *const priv = counter->priv; 523 + unsigned int count_mode; 617 524 unsigned int mode_cfg; 618 525 const int base_offset = priv->base + 2 * count->id + 1; 526 + unsigned long irqflags; 619 527 620 528 /* Map Generic Counter count mode to 104-QUAD-8 count mode */ 621 529 switch (cnt_mode) { 622 530 case COUNTER_COUNT_MODE_NORMAL: 623 - cnt_mode = 0; 531 + count_mode = 0; 624 532 break; 625 533 case COUNTER_COUNT_MODE_RANGE_LIMIT: 626 - cnt_mode = 1; 534 + count_mode = 1; 627 535 break; 628 536 case COUNTER_COUNT_MODE_NON_RECYCLE: 629 - cnt_mode = 2; 537 + count_mode = 2; 630 538 break; 631 539 case COUNTER_COUNT_MODE_MODULO_N: 632 - cnt_mode = 3; 540 + count_mode = 3; 633 541 break; 634 542 default: 635 543 /* should never reach this path */ 636 544 return -EINVAL; 637 545 } 638 546 639 - mutex_lock(&priv->lock); 547 + spin_lock_irqsave(&priv->lock, irqflags); 640 548 641 - priv->count_mode[count->id] = cnt_mode; 549 + priv->count_mode[count->id] = count_mode; 642 550 643 551 /* Set count mode configuration value */ 644 - mode_cfg = cnt_mode << 1; 552 + mode_cfg = count_mode << 1; 645 553 646 554 /* Add quadrature mode configuration */ 647 555 if (priv->quadrature_mode[count->id]) ··· 653 555 /* Load mode configuration to Counter Mode Register */ 654 556 outb(QUAD8_CTR_CMR | mode_cfg, base_offset); 655 557 656 - mutex_unlock(&priv->lock); 558 + spin_unlock_irqrestore(&priv->lock, irqflags); 657 559 658 560 return 0; 659 561 } 660 562 661 - static struct counter_count_enum_ext quad8_cnt_mode_enum = { 662 - .items = counter_count_mode_str, 663 - .num_items = ARRAY_SIZE(counter_count_mode_str), 664 - .get = quad8_count_mode_get, 665 - .set = quad8_count_mode_set 666 - }; 667 - 668 - static ssize_t quad8_count_direction_read(struct counter_device *counter, 669 - struct counter_count *count, void *priv, char *buf) 670 - { 671 - enum counter_count_direction dir; 672 - 673 - quad8_direction_get(counter, count, &dir); 674 - 675 - return sprintf(buf, "%s\n", counter_count_direction_str[dir]); 676 - } 677 - 678 - static ssize_t quad8_count_enable_read(struct counter_device *counter, 679 - struct counter_count *count, void *private, char *buf) 563 + static int quad8_count_enable_read(struct counter_device *counter, 564 + struct counter_count *count, u8 *enable) 680 565 { 681 566 const struct quad8 *const priv = counter->priv; 682 567 683 - return sprintf(buf, "%u\n", priv->ab_enable[count->id]); 568 + *enable = priv->ab_enable[count->id]; 569 + 570 + return 0; 684 571 } 685 572 686 - static ssize_t quad8_count_enable_write(struct counter_device *counter, 687 - struct counter_count *count, void *private, const char *buf, size_t len) 573 + static int quad8_count_enable_write(struct counter_device *counter, 574 + struct counter_count *count, u8 enable) 688 575 { 689 576 struct quad8 *const priv = counter->priv; 690 577 const int base_offset = priv->base + 2 * count->id; 691 - int err; 692 - bool ab_enable; 578 + unsigned long irqflags; 693 579 unsigned int ior_cfg; 694 580 695 - err = kstrtobool(buf, &ab_enable); 696 - if (err) 697 - return err; 581 + spin_lock_irqsave(&priv->lock, irqflags); 698 582 699 - mutex_lock(&priv->lock); 583 + priv->ab_enable[count->id] = enable; 700 584 701 - priv->ab_enable[count->id] = ab_enable; 702 - 703 - ior_cfg = ab_enable | priv->preset_enable[count->id] << 1; 585 + ior_cfg = enable | priv->preset_enable[count->id] << 1 | 586 + priv->irq_trigger[count->id] << 3; 704 587 705 588 /* Load I/O control configuration */ 706 589 outb(QUAD8_CTR_IOR | ior_cfg, base_offset + 1); 707 590 708 - mutex_unlock(&priv->lock); 591 + spin_unlock_irqrestore(&priv->lock, irqflags); 709 592 710 - return len; 593 + return 0; 711 594 } 712 595 713 596 static const char *const quad8_noise_error_states[] = { ··· 697 618 }; 698 619 699 620 static int quad8_error_noise_get(struct counter_device *counter, 700 - struct counter_count *count, size_t *noise_error) 621 + struct counter_count *count, u32 *noise_error) 701 622 { 702 623 const struct quad8 *const priv = counter->priv; 703 624 const int base_offset = priv->base + 2 * count->id + 1; ··· 707 628 return 0; 708 629 } 709 630 710 - static struct counter_count_enum_ext quad8_error_noise_enum = { 711 - .items = quad8_noise_error_states, 712 - .num_items = ARRAY_SIZE(quad8_noise_error_states), 713 - .get = quad8_error_noise_get 714 - }; 715 - 716 - static ssize_t quad8_count_preset_read(struct counter_device *counter, 717 - struct counter_count *count, void *private, char *buf) 631 + static int quad8_count_preset_read(struct counter_device *counter, 632 + struct counter_count *count, u64 *preset) 718 633 { 719 634 const struct quad8 *const priv = counter->priv; 720 635 721 - return sprintf(buf, "%u\n", priv->preset[count->id]); 636 + *preset = priv->preset[count->id]; 637 + 638 + return 0; 722 639 } 723 640 724 641 static void quad8_preset_register_set(struct quad8 *const priv, const int id, ··· 733 658 outb(preset >> (8 * i), base_offset); 734 659 } 735 660 736 - static ssize_t quad8_count_preset_write(struct counter_device *counter, 737 - struct counter_count *count, void *private, const char *buf, size_t len) 661 + static int quad8_count_preset_write(struct counter_device *counter, 662 + struct counter_count *count, u64 preset) 738 663 { 739 664 struct quad8 *const priv = counter->priv; 740 - unsigned int preset; 741 - int ret; 742 - 743 - ret = kstrtouint(buf, 0, &preset); 744 - if (ret) 745 - return ret; 665 + unsigned long irqflags; 746 666 747 667 /* Only 24-bit values are supported */ 748 668 if (preset > 0xFFFFFF) 749 669 return -ERANGE; 750 670 751 - mutex_lock(&priv->lock); 671 + spin_lock_irqsave(&priv->lock, irqflags); 752 672 753 673 quad8_preset_register_set(priv, count->id, preset); 754 674 755 - mutex_unlock(&priv->lock); 675 + spin_unlock_irqrestore(&priv->lock, irqflags); 756 676 757 - return len; 677 + return 0; 758 678 } 759 679 760 - static ssize_t quad8_count_ceiling_read(struct counter_device *counter, 761 - struct counter_count *count, void *private, char *buf) 680 + static int quad8_count_ceiling_read(struct counter_device *counter, 681 + struct counter_count *count, u64 *ceiling) 762 682 { 763 683 struct quad8 *const priv = counter->priv; 684 + unsigned long irqflags; 764 685 765 - mutex_lock(&priv->lock); 686 + spin_lock_irqsave(&priv->lock, irqflags); 766 687 767 688 /* Range Limit and Modulo-N count modes use preset value as ceiling */ 768 689 switch (priv->count_mode[count->id]) { 769 690 case 1: 770 691 case 3: 771 - mutex_unlock(&priv->lock); 772 - return sprintf(buf, "%u\n", priv->preset[count->id]); 692 + *ceiling = priv->preset[count->id]; 693 + break; 694 + default: 695 + /* By default 0x1FFFFFF (25 bits unsigned) is maximum count */ 696 + *ceiling = 0x1FFFFFF; 697 + break; 773 698 } 774 699 775 - mutex_unlock(&priv->lock); 700 + spin_unlock_irqrestore(&priv->lock, irqflags); 776 701 777 - /* By default 0x1FFFFFF (25 bits unsigned) is maximum count */ 778 - return sprintf(buf, "33554431\n"); 702 + return 0; 779 703 } 780 704 781 - static ssize_t quad8_count_ceiling_write(struct counter_device *counter, 782 - struct counter_count *count, void *private, const char *buf, size_t len) 705 + static int quad8_count_ceiling_write(struct counter_device *counter, 706 + struct counter_count *count, u64 ceiling) 783 707 { 784 708 struct quad8 *const priv = counter->priv; 785 - unsigned int ceiling; 786 - int ret; 787 - 788 - ret = kstrtouint(buf, 0, &ceiling); 789 - if (ret) 790 - return ret; 709 + unsigned long irqflags; 791 710 792 711 /* Only 24-bit values are supported */ 793 712 if (ceiling > 0xFFFFFF) 794 713 return -ERANGE; 795 714 796 - mutex_lock(&priv->lock); 715 + spin_lock_irqsave(&priv->lock, irqflags); 797 716 798 717 /* Range Limit and Modulo-N count modes use preset value as ceiling */ 799 718 switch (priv->count_mode[count->id]) { 800 719 case 1: 801 720 case 3: 802 721 quad8_preset_register_set(priv, count->id, ceiling); 803 - mutex_unlock(&priv->lock); 804 - return len; 722 + spin_unlock_irqrestore(&priv->lock, irqflags); 723 + return 0; 805 724 } 806 725 807 - mutex_unlock(&priv->lock); 726 + spin_unlock_irqrestore(&priv->lock, irqflags); 808 727 809 728 return -EINVAL; 810 729 } 811 730 812 - static ssize_t quad8_count_preset_enable_read(struct counter_device *counter, 813 - struct counter_count *count, void *private, char *buf) 731 + static int quad8_count_preset_enable_read(struct counter_device *counter, 732 + struct counter_count *count, 733 + u8 *preset_enable) 814 734 { 815 735 const struct quad8 *const priv = counter->priv; 816 736 817 - return sprintf(buf, "%u\n", !priv->preset_enable[count->id]); 737 + *preset_enable = !priv->preset_enable[count->id]; 738 + 739 + return 0; 818 740 } 819 741 820 - static ssize_t quad8_count_preset_enable_write(struct counter_device *counter, 821 - struct counter_count *count, void *private, const char *buf, size_t len) 742 + static int quad8_count_preset_enable_write(struct counter_device *counter, 743 + struct counter_count *count, 744 + u8 preset_enable) 822 745 { 823 746 struct quad8 *const priv = counter->priv; 824 747 const int base_offset = priv->base + 2 * count->id + 1; 825 - bool preset_enable; 826 - int ret; 748 + unsigned long irqflags; 827 749 unsigned int ior_cfg; 828 - 829 - ret = kstrtobool(buf, &preset_enable); 830 - if (ret) 831 - return ret; 832 750 833 751 /* Preset enable is active low in Input/Output Control register */ 834 752 preset_enable = !preset_enable; 835 753 836 - mutex_lock(&priv->lock); 754 + spin_lock_irqsave(&priv->lock, irqflags); 837 755 838 756 priv->preset_enable[count->id] = preset_enable; 839 757 840 - ior_cfg = priv->ab_enable[count->id] | (unsigned int)preset_enable << 1; 758 + ior_cfg = priv->ab_enable[count->id] | preset_enable << 1 | 759 + priv->irq_trigger[count->id] << 3; 841 760 842 761 /* Load I/O control configuration to Input / Output Control Register */ 843 762 outb(QUAD8_CTR_IOR | ior_cfg, base_offset); 844 763 845 - mutex_unlock(&priv->lock); 764 + spin_unlock_irqrestore(&priv->lock, irqflags); 846 765 847 - return len; 766 + return 0; 848 767 } 849 768 850 - static ssize_t quad8_signal_cable_fault_read(struct counter_device *counter, 851 - struct counter_signal *signal, 852 - void *private, char *buf) 769 + static int quad8_signal_cable_fault_read(struct counter_device *counter, 770 + struct counter_signal *signal, 771 + u8 *cable_fault) 853 772 { 854 773 struct quad8 *const priv = counter->priv; 855 774 const size_t channel_id = signal->id / 2; 775 + unsigned long irqflags; 856 776 bool disabled; 857 777 unsigned int status; 858 - unsigned int fault; 859 778 860 - mutex_lock(&priv->lock); 779 + spin_lock_irqsave(&priv->lock, irqflags); 861 780 862 781 disabled = !(priv->cable_fault_enable & BIT(channel_id)); 863 782 864 783 if (disabled) { 865 - mutex_unlock(&priv->lock); 784 + spin_unlock_irqrestore(&priv->lock, irqflags); 866 785 return -EINVAL; 867 786 } 868 787 869 788 /* Logic 0 = cable fault */ 870 789 status = inb(priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS); 871 790 872 - mutex_unlock(&priv->lock); 791 + spin_unlock_irqrestore(&priv->lock, irqflags); 873 792 874 793 /* Mask respective channel and invert logic */ 875 - fault = !(status & BIT(channel_id)); 794 + *cable_fault = !(status & BIT(channel_id)); 876 795 877 - return sprintf(buf, "%u\n", fault); 796 + return 0; 878 797 } 879 798 880 - static ssize_t quad8_signal_cable_fault_enable_read( 881 - struct counter_device *counter, struct counter_signal *signal, 882 - void *private, char *buf) 799 + static int quad8_signal_cable_fault_enable_read(struct counter_device *counter, 800 + struct counter_signal *signal, 801 + u8 *enable) 883 802 { 884 803 const struct quad8 *const priv = counter->priv; 885 804 const size_t channel_id = signal->id / 2; 886 - const unsigned int enb = !!(priv->cable_fault_enable & BIT(channel_id)); 887 805 888 - return sprintf(buf, "%u\n", enb); 806 + *enable = !!(priv->cable_fault_enable & BIT(channel_id)); 807 + 808 + return 0; 889 809 } 890 810 891 - static ssize_t quad8_signal_cable_fault_enable_write( 892 - struct counter_device *counter, struct counter_signal *signal, 893 - void *private, const char *buf, size_t len) 811 + static int quad8_signal_cable_fault_enable_write(struct counter_device *counter, 812 + struct counter_signal *signal, 813 + u8 enable) 894 814 { 895 815 struct quad8 *const priv = counter->priv; 896 816 const size_t channel_id = signal->id / 2; 897 - bool enable; 898 - int ret; 817 + unsigned long irqflags; 899 818 unsigned int cable_fault_enable; 900 819 901 - ret = kstrtobool(buf, &enable); 902 - if (ret) 903 - return ret; 904 - 905 - mutex_lock(&priv->lock); 820 + spin_lock_irqsave(&priv->lock, irqflags); 906 821 907 822 if (enable) 908 823 priv->cable_fault_enable |= BIT(channel_id); ··· 904 839 905 840 outb(cable_fault_enable, priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS); 906 841 907 - mutex_unlock(&priv->lock); 842 + spin_unlock_irqrestore(&priv->lock, irqflags); 908 843 909 - return len; 844 + return 0; 910 845 } 911 846 912 - static ssize_t quad8_signal_fck_prescaler_read(struct counter_device *counter, 913 - struct counter_signal *signal, void *private, char *buf) 847 + static int quad8_signal_fck_prescaler_read(struct counter_device *counter, 848 + struct counter_signal *signal, 849 + u8 *prescaler) 914 850 { 915 851 const struct quad8 *const priv = counter->priv; 916 - const size_t channel_id = signal->id / 2; 917 852 918 - return sprintf(buf, "%u\n", priv->fck_prescaler[channel_id]); 853 + *prescaler = priv->fck_prescaler[signal->id / 2]; 854 + 855 + return 0; 919 856 } 920 857 921 - static ssize_t quad8_signal_fck_prescaler_write(struct counter_device *counter, 922 - struct counter_signal *signal, void *private, const char *buf, 923 - size_t len) 858 + static int quad8_signal_fck_prescaler_write(struct counter_device *counter, 859 + struct counter_signal *signal, 860 + u8 prescaler) 924 861 { 925 862 struct quad8 *const priv = counter->priv; 926 863 const size_t channel_id = signal->id / 2; 927 864 const int base_offset = priv->base + 2 * channel_id; 928 - u8 prescaler; 929 - int ret; 865 + unsigned long irqflags; 930 866 931 - ret = kstrtou8(buf, 0, &prescaler); 932 - if (ret) 933 - return ret; 934 - 935 - mutex_lock(&priv->lock); 867 + spin_lock_irqsave(&priv->lock, irqflags); 936 868 937 869 priv->fck_prescaler[channel_id] = prescaler; 938 870 ··· 941 879 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC, 942 880 base_offset + 1); 943 881 944 - mutex_unlock(&priv->lock); 882 + spin_unlock_irqrestore(&priv->lock, irqflags); 945 883 946 - return len; 884 + return 0; 947 885 } 948 886 949 - static const struct counter_signal_ext quad8_signal_ext[] = { 950 - { 951 - .name = "cable_fault", 952 - .read = quad8_signal_cable_fault_read 953 - }, 954 - { 955 - .name = "cable_fault_enable", 956 - .read = quad8_signal_cable_fault_enable_read, 957 - .write = quad8_signal_cable_fault_enable_write 958 - }, 959 - { 960 - .name = "filter_clock_prescaler", 961 - .read = quad8_signal_fck_prescaler_read, 962 - .write = quad8_signal_fck_prescaler_write 963 - } 887 + static struct counter_comp quad8_signal_ext[] = { 888 + COUNTER_COMP_SIGNAL_BOOL("cable_fault", quad8_signal_cable_fault_read, 889 + NULL), 890 + COUNTER_COMP_SIGNAL_BOOL("cable_fault_enable", 891 + quad8_signal_cable_fault_enable_read, 892 + quad8_signal_cable_fault_enable_write), 893 + COUNTER_COMP_SIGNAL_U8("filter_clock_prescaler", 894 + quad8_signal_fck_prescaler_read, 895 + quad8_signal_fck_prescaler_write) 964 896 }; 965 897 966 - static const struct counter_signal_ext quad8_index_ext[] = { 967 - COUNTER_SIGNAL_ENUM("index_polarity", &quad8_index_pol_enum), 968 - COUNTER_SIGNAL_ENUM_AVAILABLE("index_polarity", &quad8_index_pol_enum), 969 - COUNTER_SIGNAL_ENUM("synchronous_mode", &quad8_syn_mode_enum), 970 - COUNTER_SIGNAL_ENUM_AVAILABLE("synchronous_mode", &quad8_syn_mode_enum) 898 + static DEFINE_COUNTER_ENUM(quad8_index_pol_enum, quad8_index_polarity_modes); 899 + static DEFINE_COUNTER_ENUM(quad8_synch_mode_enum, quad8_synchronous_modes); 900 + 901 + static struct counter_comp quad8_index_ext[] = { 902 + COUNTER_COMP_SIGNAL_ENUM("index_polarity", quad8_index_polarity_get, 903 + quad8_index_polarity_set, 904 + quad8_index_pol_enum), 905 + COUNTER_COMP_SIGNAL_ENUM("synchronous_mode", quad8_synchronous_mode_get, 906 + quad8_synchronous_mode_set, 907 + quad8_synch_mode_enum), 971 908 }; 972 909 973 910 #define QUAD8_QUAD_SIGNAL(_id, _name) { \ ··· 1035 974 QUAD8_COUNT_SYNAPSES(6), QUAD8_COUNT_SYNAPSES(7) 1036 975 }; 1037 976 1038 - static const struct counter_count_ext quad8_count_ext[] = { 1039 - { 1040 - .name = "ceiling", 1041 - .read = quad8_count_ceiling_read, 1042 - .write = quad8_count_ceiling_write 1043 - }, 1044 - { 1045 - .name = "floor", 1046 - .read = quad8_count_floor_read 1047 - }, 1048 - COUNTER_COUNT_ENUM("count_mode", &quad8_cnt_mode_enum), 1049 - COUNTER_COUNT_ENUM_AVAILABLE("count_mode", &quad8_cnt_mode_enum), 1050 - { 1051 - .name = "direction", 1052 - .read = quad8_count_direction_read 1053 - }, 1054 - { 1055 - .name = "enable", 1056 - .read = quad8_count_enable_read, 1057 - .write = quad8_count_enable_write 1058 - }, 1059 - COUNTER_COUNT_ENUM("error_noise", &quad8_error_noise_enum), 1060 - COUNTER_COUNT_ENUM_AVAILABLE("error_noise", &quad8_error_noise_enum), 1061 - { 1062 - .name = "preset", 1063 - .read = quad8_count_preset_read, 1064 - .write = quad8_count_preset_write 1065 - }, 1066 - { 1067 - .name = "preset_enable", 1068 - .read = quad8_count_preset_enable_read, 1069 - .write = quad8_count_preset_enable_write 1070 - } 977 + static const enum counter_count_mode quad8_cnt_modes[] = { 978 + COUNTER_COUNT_MODE_NORMAL, 979 + COUNTER_COUNT_MODE_RANGE_LIMIT, 980 + COUNTER_COUNT_MODE_NON_RECYCLE, 981 + COUNTER_COUNT_MODE_MODULO_N, 982 + }; 983 + 984 + static DEFINE_COUNTER_AVAILABLE(quad8_count_mode_available, quad8_cnt_modes); 985 + 986 + static DEFINE_COUNTER_ENUM(quad8_error_noise_enum, quad8_noise_error_states); 987 + 988 + static struct counter_comp quad8_count_ext[] = { 989 + COUNTER_COMP_CEILING(quad8_count_ceiling_read, 990 + quad8_count_ceiling_write), 991 + COUNTER_COMP_FLOOR(quad8_count_floor_read, NULL), 992 + COUNTER_COMP_COUNT_MODE(quad8_count_mode_read, quad8_count_mode_write, 993 + quad8_count_mode_available), 994 + COUNTER_COMP_DIRECTION(quad8_direction_read), 995 + COUNTER_COMP_ENABLE(quad8_count_enable_read, quad8_count_enable_write), 996 + COUNTER_COMP_COUNT_ENUM("error_noise", quad8_error_noise_get, NULL, 997 + quad8_error_noise_enum), 998 + COUNTER_COMP_PRESET(quad8_count_preset_read, quad8_count_preset_write), 999 + COUNTER_COMP_PRESET_ENABLE(quad8_count_preset_enable_read, 1000 + quad8_count_preset_enable_write), 1071 1001 }; 1072 1002 1073 1003 #define QUAD8_COUNT(_id, _cntname) { \ ··· 1083 1031 QUAD8_COUNT(7, "Channel 8 Count") 1084 1032 }; 1085 1033 1034 + static irqreturn_t quad8_irq_handler(int irq, void *private) 1035 + { 1036 + struct quad8 *const priv = private; 1037 + const unsigned long base = priv->base; 1038 + unsigned long irq_status; 1039 + unsigned long channel; 1040 + u8 event; 1041 + 1042 + irq_status = inb(base + QUAD8_REG_INTERRUPT_STATUS); 1043 + if (!irq_status) 1044 + return IRQ_NONE; 1045 + 1046 + for_each_set_bit(channel, &irq_status, QUAD8_NUM_COUNTERS) { 1047 + switch (priv->irq_trigger[channel]) { 1048 + case QUAD8_EVENT_CARRY: 1049 + event = COUNTER_EVENT_OVERFLOW; 1050 + break; 1051 + case QUAD8_EVENT_COMPARE: 1052 + event = COUNTER_EVENT_THRESHOLD; 1053 + break; 1054 + case QUAD8_EVENT_CARRY_BORROW: 1055 + event = COUNTER_EVENT_OVERFLOW_UNDERFLOW; 1056 + break; 1057 + case QUAD8_EVENT_INDEX: 1058 + event = COUNTER_EVENT_INDEX; 1059 + break; 1060 + default: 1061 + /* should never reach this path */ 1062 + WARN_ONCE(true, "invalid interrupt trigger function %u configured for channel %lu\n", 1063 + priv->irq_trigger[channel], channel); 1064 + continue; 1065 + } 1066 + 1067 + counter_push_event(&priv->counter, event, channel); 1068 + } 1069 + 1070 + /* Clear pending interrupts on device */ 1071 + outb(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, base + QUAD8_REG_CHAN_OP); 1072 + 1073 + return IRQ_HANDLED; 1074 + } 1075 + 1086 1076 static int quad8_probe(struct device *dev, unsigned int id) 1087 1077 { 1088 1078 struct quad8 *priv; 1089 1079 int i, j; 1090 1080 unsigned int base_offset; 1081 + int err; 1091 1082 1092 1083 if (!devm_request_region(dev, base[id], QUAD8_EXTENT, dev_name(dev))) { 1093 1084 dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", ··· 1153 1058 priv->counter.priv = priv; 1154 1059 priv->base = base[id]; 1155 1060 1156 - /* Initialize mutex */ 1157 - mutex_init(&priv->lock); 1061 + spin_lock_init(&priv->lock); 1158 1062 1063 + /* Reset Index/Interrupt Register */ 1064 + outb(0x00, base[id] + QUAD8_REG_INDEX_INTERRUPT); 1159 1065 /* Reset all counters and disable interrupt function */ 1160 1066 outb(QUAD8_CHAN_OP_RESET_COUNTERS, base[id] + QUAD8_REG_CHAN_OP); 1161 1067 /* Set initial configuration for all counters */ ··· 1183 1087 outb(QUAD8_CTR_IOR, base_offset + 1); 1184 1088 /* Disable index function; negative index polarity */ 1185 1089 outb(QUAD8_CTR_IDR, base_offset + 1); 1090 + /* Initialize next IRQ trigger function configuration */ 1091 + priv->next_irq_trigger[i] = QUAD8_EVENT_NONE; 1186 1092 } 1187 1093 /* Disable Differential Encoder Cable Status for all channels */ 1188 1094 outb(0xFF, base[id] + QUAD8_DIFF_ENCODER_CABLE_STATUS); 1189 - /* Enable all counters */ 1190 - outb(QUAD8_CHAN_OP_ENABLE_COUNTERS, base[id] + QUAD8_REG_CHAN_OP); 1095 + /* Enable all counters and enable interrupt function */ 1096 + outb(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, base[id] + QUAD8_REG_CHAN_OP); 1097 + 1098 + err = devm_request_irq(dev, irq[id], quad8_irq_handler, IRQF_SHARED, 1099 + priv->counter.name, priv); 1100 + if (err) 1101 + return err; 1191 1102 1192 1103 return devm_counter_register(dev, &priv->counter); 1193 1104 }
+3 -3
drivers/counter/Kconfig
··· 23 23 A counter's respective error flag may be cleared by performing a write 24 24 operation on the respective count value attribute. Although the 25 25 104-QUAD-8 counters have a 25-bit range, only the lower 24 bits may be 26 - set, either directly or via the counter's preset attribute. Interrupts 27 - are not supported by this driver. 26 + set, either directly or via the counter's preset attribute. 28 27 29 28 The base port addresses for the devices may be configured via the base 30 - array module parameter. 29 + array module parameter. The interrupt line numbers for the devices may 30 + be configured via the irq array module parameter. 31 31 32 32 config INTERRUPT_CNT 33 33 tristate "Interrupt counter driver"
+1
drivers/counter/Makefile
··· 4 4 # 5 5 6 6 obj-$(CONFIG_COUNTER) += counter.o 7 + counter-y := counter-core.o counter-sysfs.o counter-chrdev.o 7 8 8 9 obj-$(CONFIG_104_QUAD_8) += 104-quad-8.o 9 10 obj-$(CONFIG_INTERRUPT_CNT) += interrupt-cnt.o
+578
drivers/counter/counter-chrdev.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Generic Counter character device interface 4 + * Copyright (C) 2020 William Breathitt Gray 5 + */ 6 + #include <linux/atomic.h> 7 + #include <linux/cdev.h> 8 + #include <linux/counter.h> 9 + #include <linux/err.h> 10 + #include <linux/errno.h> 11 + #include <linux/export.h> 12 + #include <linux/fs.h> 13 + #include <linux/kfifo.h> 14 + #include <linux/list.h> 15 + #include <linux/mutex.h> 16 + #include <linux/nospec.h> 17 + #include <linux/poll.h> 18 + #include <linux/slab.h> 19 + #include <linux/spinlock.h> 20 + #include <linux/timekeeping.h> 21 + #include <linux/types.h> 22 + #include <linux/uaccess.h> 23 + #include <linux/wait.h> 24 + 25 + #include "counter-chrdev.h" 26 + 27 + struct counter_comp_node { 28 + struct list_head l; 29 + struct counter_component component; 30 + struct counter_comp comp; 31 + void *parent; 32 + }; 33 + 34 + #define counter_comp_read_is_equal(a, b) \ 35 + (a.action_read == b.action_read || \ 36 + a.device_u8_read == b.device_u8_read || \ 37 + a.count_u8_read == b.count_u8_read || \ 38 + a.signal_u8_read == b.signal_u8_read || \ 39 + a.device_u32_read == b.device_u32_read || \ 40 + a.count_u32_read == b.count_u32_read || \ 41 + a.signal_u32_read == b.signal_u32_read || \ 42 + a.device_u64_read == b.device_u64_read || \ 43 + a.count_u64_read == b.count_u64_read || \ 44 + a.signal_u64_read == b.signal_u64_read) 45 + 46 + #define counter_comp_read_is_set(comp) \ 47 + (comp.action_read || \ 48 + comp.device_u8_read || \ 49 + comp.count_u8_read || \ 50 + comp.signal_u8_read || \ 51 + comp.device_u32_read || \ 52 + comp.count_u32_read || \ 53 + comp.signal_u32_read || \ 54 + comp.device_u64_read || \ 55 + comp.count_u64_read || \ 56 + comp.signal_u64_read) 57 + 58 + static ssize_t counter_chrdev_read(struct file *filp, char __user *buf, 59 + size_t len, loff_t *f_ps) 60 + { 61 + struct counter_device *const counter = filp->private_data; 62 + int err; 63 + unsigned int copied; 64 + 65 + if (!counter->ops) 66 + return -ENODEV; 67 + 68 + if (len < sizeof(struct counter_event)) 69 + return -EINVAL; 70 + 71 + do { 72 + if (kfifo_is_empty(&counter->events)) { 73 + if (filp->f_flags & O_NONBLOCK) 74 + return -EAGAIN; 75 + 76 + err = wait_event_interruptible(counter->events_wait, 77 + !kfifo_is_empty(&counter->events) || 78 + !counter->ops); 79 + if (err < 0) 80 + return err; 81 + if (!counter->ops) 82 + return -ENODEV; 83 + } 84 + 85 + if (mutex_lock_interruptible(&counter->events_lock)) 86 + return -ERESTARTSYS; 87 + err = kfifo_to_user(&counter->events, buf, len, &copied); 88 + mutex_unlock(&counter->events_lock); 89 + if (err < 0) 90 + return err; 91 + } while (!copied); 92 + 93 + return copied; 94 + } 95 + 96 + static __poll_t counter_chrdev_poll(struct file *filp, 97 + struct poll_table_struct *pollt) 98 + { 99 + struct counter_device *const counter = filp->private_data; 100 + __poll_t events = 0; 101 + 102 + if (!counter->ops) 103 + return events; 104 + 105 + poll_wait(filp, &counter->events_wait, pollt); 106 + 107 + if (!kfifo_is_empty(&counter->events)) 108 + events = EPOLLIN | EPOLLRDNORM; 109 + 110 + return events; 111 + } 112 + 113 + static void counter_events_list_free(struct list_head *const events_list) 114 + { 115 + struct counter_event_node *p, *n; 116 + struct counter_comp_node *q, *o; 117 + 118 + list_for_each_entry_safe(p, n, events_list, l) { 119 + /* Free associated component nodes */ 120 + list_for_each_entry_safe(q, o, &p->comp_list, l) { 121 + list_del(&q->l); 122 + kfree(q); 123 + } 124 + 125 + /* Free event node */ 126 + list_del(&p->l); 127 + kfree(p); 128 + } 129 + } 130 + 131 + static int counter_set_event_node(struct counter_device *const counter, 132 + struct counter_watch *const watch, 133 + const struct counter_comp_node *const cfg) 134 + { 135 + struct counter_event_node *event_node; 136 + int err = 0; 137 + struct counter_comp_node *comp_node; 138 + 139 + /* Search for event in the list */ 140 + list_for_each_entry(event_node, &counter->next_events_list, l) 141 + if (event_node->event == watch->event && 142 + event_node->channel == watch->channel) 143 + break; 144 + 145 + /* If event is not already in the list */ 146 + if (&event_node->l == &counter->next_events_list) { 147 + /* Allocate new event node */ 148 + event_node = kmalloc(sizeof(*event_node), GFP_KERNEL); 149 + if (!event_node) 150 + return -ENOMEM; 151 + 152 + /* Configure event node and add to the list */ 153 + event_node->event = watch->event; 154 + event_node->channel = watch->channel; 155 + INIT_LIST_HEAD(&event_node->comp_list); 156 + list_add(&event_node->l, &counter->next_events_list); 157 + } 158 + 159 + /* Check if component watch has already been set before */ 160 + list_for_each_entry(comp_node, &event_node->comp_list, l) 161 + if (comp_node->parent == cfg->parent && 162 + counter_comp_read_is_equal(comp_node->comp, cfg->comp)) { 163 + err = -EINVAL; 164 + goto exit_free_event_node; 165 + } 166 + 167 + /* Allocate component node */ 168 + comp_node = kmalloc(sizeof(*comp_node), GFP_KERNEL); 169 + if (!comp_node) { 170 + err = -ENOMEM; 171 + goto exit_free_event_node; 172 + } 173 + *comp_node = *cfg; 174 + 175 + /* Add component node to event node */ 176 + list_add_tail(&comp_node->l, &event_node->comp_list); 177 + 178 + exit_free_event_node: 179 + /* Free event node if no one else is watching */ 180 + if (list_empty(&event_node->comp_list)) { 181 + list_del(&event_node->l); 182 + kfree(event_node); 183 + } 184 + 185 + return err; 186 + } 187 + 188 + static int counter_enable_events(struct counter_device *const counter) 189 + { 190 + unsigned long flags; 191 + int err = 0; 192 + 193 + mutex_lock(&counter->n_events_list_lock); 194 + spin_lock_irqsave(&counter->events_list_lock, flags); 195 + 196 + counter_events_list_free(&counter->events_list); 197 + list_replace_init(&counter->next_events_list, 198 + &counter->events_list); 199 + 200 + if (counter->ops->events_configure) 201 + err = counter->ops->events_configure(counter); 202 + 203 + spin_unlock_irqrestore(&counter->events_list_lock, flags); 204 + mutex_unlock(&counter->n_events_list_lock); 205 + 206 + return err; 207 + } 208 + 209 + static int counter_disable_events(struct counter_device *const counter) 210 + { 211 + unsigned long flags; 212 + int err = 0; 213 + 214 + spin_lock_irqsave(&counter->events_list_lock, flags); 215 + 216 + counter_events_list_free(&counter->events_list); 217 + 218 + if (counter->ops->events_configure) 219 + err = counter->ops->events_configure(counter); 220 + 221 + spin_unlock_irqrestore(&counter->events_list_lock, flags); 222 + 223 + mutex_lock(&counter->n_events_list_lock); 224 + 225 + counter_events_list_free(&counter->next_events_list); 226 + 227 + mutex_unlock(&counter->n_events_list_lock); 228 + 229 + return err; 230 + } 231 + 232 + static int counter_add_watch(struct counter_device *const counter, 233 + const unsigned long arg) 234 + { 235 + void __user *const uwatch = (void __user *)arg; 236 + struct counter_watch watch; 237 + struct counter_comp_node comp_node = {}; 238 + size_t parent, id; 239 + struct counter_comp *ext; 240 + size_t num_ext; 241 + int err = 0; 242 + 243 + if (copy_from_user(&watch, uwatch, sizeof(watch))) 244 + return -EFAULT; 245 + 246 + if (watch.component.type == COUNTER_COMPONENT_NONE) 247 + goto no_component; 248 + 249 + parent = watch.component.parent; 250 + 251 + /* Configure parent component info for comp node */ 252 + switch (watch.component.scope) { 253 + case COUNTER_SCOPE_DEVICE: 254 + ext = counter->ext; 255 + num_ext = counter->num_ext; 256 + break; 257 + case COUNTER_SCOPE_SIGNAL: 258 + if (parent >= counter->num_signals) 259 + return -EINVAL; 260 + parent = array_index_nospec(parent, counter->num_signals); 261 + 262 + comp_node.parent = counter->signals + parent; 263 + 264 + ext = counter->signals[parent].ext; 265 + num_ext = counter->signals[parent].num_ext; 266 + break; 267 + case COUNTER_SCOPE_COUNT: 268 + if (parent >= counter->num_counts) 269 + return -EINVAL; 270 + parent = array_index_nospec(parent, counter->num_counts); 271 + 272 + comp_node.parent = counter->counts + parent; 273 + 274 + ext = counter->counts[parent].ext; 275 + num_ext = counter->counts[parent].num_ext; 276 + break; 277 + default: 278 + return -EINVAL; 279 + } 280 + 281 + id = watch.component.id; 282 + 283 + /* Configure component info for comp node */ 284 + switch (watch.component.type) { 285 + case COUNTER_COMPONENT_SIGNAL: 286 + if (watch.component.scope != COUNTER_SCOPE_SIGNAL) 287 + return -EINVAL; 288 + 289 + comp_node.comp.type = COUNTER_COMP_SIGNAL_LEVEL; 290 + comp_node.comp.signal_u32_read = counter->ops->signal_read; 291 + break; 292 + case COUNTER_COMPONENT_COUNT: 293 + if (watch.component.scope != COUNTER_SCOPE_COUNT) 294 + return -EINVAL; 295 + 296 + comp_node.comp.type = COUNTER_COMP_U64; 297 + comp_node.comp.count_u64_read = counter->ops->count_read; 298 + break; 299 + case COUNTER_COMPONENT_FUNCTION: 300 + if (watch.component.scope != COUNTER_SCOPE_COUNT) 301 + return -EINVAL; 302 + 303 + comp_node.comp.type = COUNTER_COMP_FUNCTION; 304 + comp_node.comp.count_u32_read = counter->ops->function_read; 305 + break; 306 + case COUNTER_COMPONENT_SYNAPSE_ACTION: 307 + if (watch.component.scope != COUNTER_SCOPE_COUNT) 308 + return -EINVAL; 309 + if (id >= counter->counts[parent].num_synapses) 310 + return -EINVAL; 311 + id = array_index_nospec(id, counter->counts[parent].num_synapses); 312 + 313 + comp_node.comp.type = COUNTER_COMP_SYNAPSE_ACTION; 314 + comp_node.comp.action_read = counter->ops->action_read; 315 + comp_node.comp.priv = counter->counts[parent].synapses + id; 316 + break; 317 + case COUNTER_COMPONENT_EXTENSION: 318 + if (id >= num_ext) 319 + return -EINVAL; 320 + id = array_index_nospec(id, num_ext); 321 + 322 + comp_node.comp = ext[id]; 323 + break; 324 + default: 325 + return -EINVAL; 326 + } 327 + if (!counter_comp_read_is_set(comp_node.comp)) 328 + return -EOPNOTSUPP; 329 + 330 + no_component: 331 + mutex_lock(&counter->n_events_list_lock); 332 + 333 + if (counter->ops->watch_validate) { 334 + err = counter->ops->watch_validate(counter, &watch); 335 + if (err < 0) 336 + goto err_exit; 337 + } 338 + 339 + comp_node.component = watch.component; 340 + 341 + err = counter_set_event_node(counter, &watch, &comp_node); 342 + 343 + err_exit: 344 + mutex_unlock(&counter->n_events_list_lock); 345 + 346 + return err; 347 + } 348 + 349 + static long counter_chrdev_ioctl(struct file *filp, unsigned int cmd, 350 + unsigned long arg) 351 + { 352 + struct counter_device *const counter = filp->private_data; 353 + int ret = -ENODEV; 354 + 355 + mutex_lock(&counter->ops_exist_lock); 356 + 357 + if (!counter->ops) 358 + goto out_unlock; 359 + 360 + switch (cmd) { 361 + case COUNTER_ADD_WATCH_IOCTL: 362 + ret = counter_add_watch(counter, arg); 363 + break; 364 + case COUNTER_ENABLE_EVENTS_IOCTL: 365 + ret = counter_enable_events(counter); 366 + break; 367 + case COUNTER_DISABLE_EVENTS_IOCTL: 368 + ret = counter_disable_events(counter); 369 + break; 370 + default: 371 + ret = -ENOIOCTLCMD; 372 + break; 373 + } 374 + 375 + out_unlock: 376 + mutex_unlock(&counter->ops_exist_lock); 377 + 378 + return ret; 379 + } 380 + 381 + static int counter_chrdev_open(struct inode *inode, struct file *filp) 382 + { 383 + struct counter_device *const counter = container_of(inode->i_cdev, 384 + typeof(*counter), 385 + chrdev); 386 + 387 + /* Ensure chrdev is not opened more than 1 at a time */ 388 + if (!atomic_add_unless(&counter->chrdev_lock, 1, 1)) 389 + return -EBUSY; 390 + 391 + get_device(&counter->dev); 392 + filp->private_data = counter; 393 + 394 + return nonseekable_open(inode, filp); 395 + } 396 + 397 + static int counter_chrdev_release(struct inode *inode, struct file *filp) 398 + { 399 + struct counter_device *const counter = filp->private_data; 400 + int ret = 0; 401 + 402 + mutex_lock(&counter->ops_exist_lock); 403 + 404 + if (!counter->ops) { 405 + /* Free any lingering held memory */ 406 + counter_events_list_free(&counter->events_list); 407 + counter_events_list_free(&counter->next_events_list); 408 + ret = -ENODEV; 409 + goto out_unlock; 410 + } 411 + 412 + ret = counter_disable_events(counter); 413 + if (ret < 0) { 414 + mutex_unlock(&counter->ops_exist_lock); 415 + return ret; 416 + } 417 + 418 + out_unlock: 419 + mutex_unlock(&counter->ops_exist_lock); 420 + 421 + put_device(&counter->dev); 422 + atomic_dec(&counter->chrdev_lock); 423 + 424 + return ret; 425 + } 426 + 427 + static const struct file_operations counter_fops = { 428 + .owner = THIS_MODULE, 429 + .llseek = no_llseek, 430 + .read = counter_chrdev_read, 431 + .poll = counter_chrdev_poll, 432 + .unlocked_ioctl = counter_chrdev_ioctl, 433 + .open = counter_chrdev_open, 434 + .release = counter_chrdev_release, 435 + }; 436 + 437 + int counter_chrdev_add(struct counter_device *const counter) 438 + { 439 + /* Initialize Counter events lists */ 440 + INIT_LIST_HEAD(&counter->events_list); 441 + INIT_LIST_HEAD(&counter->next_events_list); 442 + spin_lock_init(&counter->events_list_lock); 443 + mutex_init(&counter->n_events_list_lock); 444 + init_waitqueue_head(&counter->events_wait); 445 + mutex_init(&counter->events_lock); 446 + 447 + /* Initialize character device */ 448 + atomic_set(&counter->chrdev_lock, 0); 449 + cdev_init(&counter->chrdev, &counter_fops); 450 + 451 + /* Allocate Counter events queue */ 452 + return kfifo_alloc(&counter->events, 64, GFP_KERNEL); 453 + } 454 + 455 + void counter_chrdev_remove(struct counter_device *const counter) 456 + { 457 + kfifo_free(&counter->events); 458 + } 459 + 460 + static int counter_get_data(struct counter_device *const counter, 461 + const struct counter_comp_node *const comp_node, 462 + u64 *const value) 463 + { 464 + const struct counter_comp *const comp = &comp_node->comp; 465 + void *const parent = comp_node->parent; 466 + u8 value_u8 = 0; 467 + u32 value_u32 = 0; 468 + int ret; 469 + 470 + if (comp_node->component.type == COUNTER_COMPONENT_NONE) 471 + return 0; 472 + 473 + switch (comp->type) { 474 + case COUNTER_COMP_U8: 475 + case COUNTER_COMP_BOOL: 476 + switch (comp_node->component.scope) { 477 + case COUNTER_SCOPE_DEVICE: 478 + ret = comp->device_u8_read(counter, &value_u8); 479 + break; 480 + case COUNTER_SCOPE_SIGNAL: 481 + ret = comp->signal_u8_read(counter, parent, &value_u8); 482 + break; 483 + case COUNTER_SCOPE_COUNT: 484 + ret = comp->count_u8_read(counter, parent, &value_u8); 485 + break; 486 + } 487 + *value = value_u8; 488 + return ret; 489 + case COUNTER_COMP_SIGNAL_LEVEL: 490 + case COUNTER_COMP_FUNCTION: 491 + case COUNTER_COMP_ENUM: 492 + case COUNTER_COMP_COUNT_DIRECTION: 493 + case COUNTER_COMP_COUNT_MODE: 494 + switch (comp_node->component.scope) { 495 + case COUNTER_SCOPE_DEVICE: 496 + ret = comp->device_u32_read(counter, &value_u32); 497 + break; 498 + case COUNTER_SCOPE_SIGNAL: 499 + ret = comp->signal_u32_read(counter, parent, 500 + &value_u32); 501 + break; 502 + case COUNTER_SCOPE_COUNT: 503 + ret = comp->count_u32_read(counter, parent, &value_u32); 504 + break; 505 + } 506 + *value = value_u32; 507 + return ret; 508 + case COUNTER_COMP_U64: 509 + switch (comp_node->component.scope) { 510 + case COUNTER_SCOPE_DEVICE: 511 + return comp->device_u64_read(counter, value); 512 + case COUNTER_SCOPE_SIGNAL: 513 + return comp->signal_u64_read(counter, parent, value); 514 + case COUNTER_SCOPE_COUNT: 515 + return comp->count_u64_read(counter, parent, value); 516 + default: 517 + return -EINVAL; 518 + } 519 + case COUNTER_COMP_SYNAPSE_ACTION: 520 + ret = comp->action_read(counter, parent, comp->priv, 521 + &value_u32); 522 + *value = value_u32; 523 + return ret; 524 + default: 525 + return -EINVAL; 526 + } 527 + } 528 + 529 + /** 530 + * counter_push_event - queue event for userspace reading 531 + * @counter: pointer to Counter structure 532 + * @event: triggered event 533 + * @channel: event channel 534 + * 535 + * Note: If no one is watching for the respective event, it is silently 536 + * discarded. 537 + */ 538 + void counter_push_event(struct counter_device *const counter, const u8 event, 539 + const u8 channel) 540 + { 541 + struct counter_event ev; 542 + unsigned int copied = 0; 543 + unsigned long flags; 544 + struct counter_event_node *event_node; 545 + struct counter_comp_node *comp_node; 546 + 547 + ev.timestamp = ktime_get_ns(); 548 + ev.watch.event = event; 549 + ev.watch.channel = channel; 550 + 551 + /* Could be in an interrupt context, so use a spin lock */ 552 + spin_lock_irqsave(&counter->events_list_lock, flags); 553 + 554 + /* Search for event in the list */ 555 + list_for_each_entry(event_node, &counter->events_list, l) 556 + if (event_node->event == event && 557 + event_node->channel == channel) 558 + break; 559 + 560 + /* If event is not in the list */ 561 + if (&event_node->l == &counter->events_list) 562 + goto exit_early; 563 + 564 + /* Read and queue relevant comp for userspace */ 565 + list_for_each_entry(comp_node, &event_node->comp_list, l) { 566 + ev.watch.component = comp_node->component; 567 + ev.status = -counter_get_data(counter, comp_node, &ev.value); 568 + 569 + copied += kfifo_in(&counter->events, &ev, 1); 570 + } 571 + 572 + exit_early: 573 + spin_unlock_irqrestore(&counter->events_list_lock, flags); 574 + 575 + if (copied) 576 + wake_up_poll(&counter->events_wait, EPOLLIN); 577 + } 578 + EXPORT_SYMBOL_GPL(counter_push_event);
+14
drivers/counter/counter-chrdev.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Counter character device interface 4 + * Copyright (C) 2020 William Breathitt Gray 5 + */ 6 + #ifndef _COUNTER_CHRDEV_H_ 7 + #define _COUNTER_CHRDEV_H_ 8 + 9 + #include <linux/counter.h> 10 + 11 + int counter_chrdev_add(struct counter_device *const counter); 12 + void counter_chrdev_remove(struct counter_device *const counter); 13 + 14 + #endif /* _COUNTER_CHRDEV_H_ */
+191
drivers/counter/counter-core.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Generic Counter interface 4 + * Copyright (C) 2020 William Breathitt Gray 5 + */ 6 + #include <linux/cdev.h> 7 + #include <linux/counter.h> 8 + #include <linux/device.h> 9 + #include <linux/device/bus.h> 10 + #include <linux/export.h> 11 + #include <linux/fs.h> 12 + #include <linux/gfp.h> 13 + #include <linux/idr.h> 14 + #include <linux/init.h> 15 + #include <linux/kdev_t.h> 16 + #include <linux/module.h> 17 + #include <linux/mutex.h> 18 + #include <linux/types.h> 19 + #include <linux/wait.h> 20 + 21 + #include "counter-chrdev.h" 22 + #include "counter-sysfs.h" 23 + 24 + /* Provides a unique ID for each counter device */ 25 + static DEFINE_IDA(counter_ida); 26 + 27 + static void counter_device_release(struct device *dev) 28 + { 29 + struct counter_device *const counter = dev_get_drvdata(dev); 30 + 31 + counter_chrdev_remove(counter); 32 + ida_free(&counter_ida, dev->id); 33 + } 34 + 35 + static struct device_type counter_device_type = { 36 + .name = "counter_device", 37 + .release = counter_device_release, 38 + }; 39 + 40 + static struct bus_type counter_bus_type = { 41 + .name = "counter", 42 + .dev_name = "counter", 43 + }; 44 + 45 + static dev_t counter_devt; 46 + 47 + /** 48 + * counter_register - register Counter to the system 49 + * @counter: pointer to Counter to register 50 + * 51 + * This function registers a Counter to the system. A sysfs "counter" directory 52 + * will be created and populated with sysfs attributes correlating with the 53 + * Counter Signals, Synapses, and Counts respectively. 54 + * 55 + * RETURNS: 56 + * 0 on success, negative error number on failure. 57 + */ 58 + int counter_register(struct counter_device *const counter) 59 + { 60 + struct device *const dev = &counter->dev; 61 + int id; 62 + int err; 63 + 64 + /* Acquire unique ID */ 65 + id = ida_alloc(&counter_ida, GFP_KERNEL); 66 + if (id < 0) 67 + return id; 68 + 69 + mutex_init(&counter->ops_exist_lock); 70 + 71 + /* Configure device structure for Counter */ 72 + dev->id = id; 73 + dev->type = &counter_device_type; 74 + dev->bus = &counter_bus_type; 75 + dev->devt = MKDEV(MAJOR(counter_devt), id); 76 + if (counter->parent) { 77 + dev->parent = counter->parent; 78 + dev->of_node = counter->parent->of_node; 79 + } 80 + device_initialize(dev); 81 + dev_set_drvdata(dev, counter); 82 + 83 + err = counter_sysfs_add(counter); 84 + if (err < 0) 85 + goto err_free_id; 86 + 87 + err = counter_chrdev_add(counter); 88 + if (err < 0) 89 + goto err_free_id; 90 + 91 + err = cdev_device_add(&counter->chrdev, dev); 92 + if (err < 0) 93 + goto err_remove_chrdev; 94 + 95 + return 0; 96 + 97 + err_remove_chrdev: 98 + counter_chrdev_remove(counter); 99 + err_free_id: 100 + put_device(dev); 101 + return err; 102 + } 103 + EXPORT_SYMBOL_GPL(counter_register); 104 + 105 + /** 106 + * counter_unregister - unregister Counter from the system 107 + * @counter: pointer to Counter to unregister 108 + * 109 + * The Counter is unregistered from the system. 110 + */ 111 + void counter_unregister(struct counter_device *const counter) 112 + { 113 + if (!counter) 114 + return; 115 + 116 + cdev_device_del(&counter->chrdev, &counter->dev); 117 + 118 + mutex_lock(&counter->ops_exist_lock); 119 + 120 + counter->ops = NULL; 121 + wake_up(&counter->events_wait); 122 + 123 + mutex_unlock(&counter->ops_exist_lock); 124 + 125 + put_device(&counter->dev); 126 + } 127 + EXPORT_SYMBOL_GPL(counter_unregister); 128 + 129 + static void devm_counter_release(void *counter) 130 + { 131 + counter_unregister(counter); 132 + } 133 + 134 + /** 135 + * devm_counter_register - Resource-managed counter_register 136 + * @dev: device to allocate counter_device for 137 + * @counter: pointer to Counter to register 138 + * 139 + * Managed counter_register. The Counter registered with this function is 140 + * automatically unregistered on driver detach. This function calls 141 + * counter_register internally. Refer to that function for more information. 142 + * 143 + * RETURNS: 144 + * 0 on success, negative error number on failure. 145 + */ 146 + int devm_counter_register(struct device *dev, 147 + struct counter_device *const counter) 148 + { 149 + int err; 150 + 151 + err = counter_register(counter); 152 + if (err < 0) 153 + return err; 154 + 155 + return devm_add_action_or_reset(dev, devm_counter_release, counter); 156 + } 157 + EXPORT_SYMBOL_GPL(devm_counter_register); 158 + 159 + #define COUNTER_DEV_MAX 256 160 + 161 + static int __init counter_init(void) 162 + { 163 + int err; 164 + 165 + err = bus_register(&counter_bus_type); 166 + if (err < 0) 167 + return err; 168 + 169 + err = alloc_chrdev_region(&counter_devt, 0, COUNTER_DEV_MAX, "counter"); 170 + if (err < 0) 171 + goto err_unregister_bus; 172 + 173 + return 0; 174 + 175 + err_unregister_bus: 176 + bus_unregister(&counter_bus_type); 177 + return err; 178 + } 179 + 180 + static void __exit counter_exit(void) 181 + { 182 + unregister_chrdev_region(counter_devt, COUNTER_DEV_MAX); 183 + bus_unregister(&counter_bus_type); 184 + } 185 + 186 + subsys_initcall(counter_init); 187 + module_exit(counter_exit); 188 + 189 + MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); 190 + MODULE_DESCRIPTION("Generic Counter interface"); 191 + MODULE_LICENSE("GPL v2");
+960
drivers/counter/counter-sysfs.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Generic Counter sysfs interface 4 + * Copyright (C) 2020 William Breathitt Gray 5 + */ 6 + #include <linux/atomic.h> 7 + #include <linux/counter.h> 8 + #include <linux/device.h> 9 + #include <linux/err.h> 10 + #include <linux/gfp.h> 11 + #include <linux/kernel.h> 12 + #include <linux/kfifo.h> 13 + #include <linux/kstrtox.h> 14 + #include <linux/list.h> 15 + #include <linux/string.h> 16 + #include <linux/sysfs.h> 17 + #include <linux/types.h> 18 + 19 + #include "counter-sysfs.h" 20 + 21 + /** 22 + * struct counter_attribute - Counter sysfs attribute 23 + * @dev_attr: device attribute for sysfs 24 + * @l: node to add Counter attribute to attribute group list 25 + * @comp: Counter component callbacks and data 26 + * @scope: Counter scope of the attribute 27 + * @parent: pointer to the parent component 28 + */ 29 + struct counter_attribute { 30 + struct device_attribute dev_attr; 31 + struct list_head l; 32 + 33 + struct counter_comp comp; 34 + enum counter_scope scope; 35 + void *parent; 36 + }; 37 + 38 + #define to_counter_attribute(_dev_attr) \ 39 + container_of(_dev_attr, struct counter_attribute, dev_attr) 40 + 41 + /** 42 + * struct counter_attribute_group - container for attribute group 43 + * @name: name of the attribute group 44 + * @attr_list: list to keep track of created attributes 45 + * @num_attr: number of attributes 46 + */ 47 + struct counter_attribute_group { 48 + const char *name; 49 + struct list_head attr_list; 50 + size_t num_attr; 51 + }; 52 + 53 + static const char *const counter_function_str[] = { 54 + [COUNTER_FUNCTION_INCREASE] = "increase", 55 + [COUNTER_FUNCTION_DECREASE] = "decrease", 56 + [COUNTER_FUNCTION_PULSE_DIRECTION] = "pulse-direction", 57 + [COUNTER_FUNCTION_QUADRATURE_X1_A] = "quadrature x1 a", 58 + [COUNTER_FUNCTION_QUADRATURE_X1_B] = "quadrature x1 b", 59 + [COUNTER_FUNCTION_QUADRATURE_X2_A] = "quadrature x2 a", 60 + [COUNTER_FUNCTION_QUADRATURE_X2_B] = "quadrature x2 b", 61 + [COUNTER_FUNCTION_QUADRATURE_X4] = "quadrature x4" 62 + }; 63 + 64 + static const char *const counter_signal_value_str[] = { 65 + [COUNTER_SIGNAL_LEVEL_LOW] = "low", 66 + [COUNTER_SIGNAL_LEVEL_HIGH] = "high" 67 + }; 68 + 69 + static const char *const counter_synapse_action_str[] = { 70 + [COUNTER_SYNAPSE_ACTION_NONE] = "none", 71 + [COUNTER_SYNAPSE_ACTION_RISING_EDGE] = "rising edge", 72 + [COUNTER_SYNAPSE_ACTION_FALLING_EDGE] = "falling edge", 73 + [COUNTER_SYNAPSE_ACTION_BOTH_EDGES] = "both edges" 74 + }; 75 + 76 + static const char *const counter_count_direction_str[] = { 77 + [COUNTER_COUNT_DIRECTION_FORWARD] = "forward", 78 + [COUNTER_COUNT_DIRECTION_BACKWARD] = "backward" 79 + }; 80 + 81 + static const char *const counter_count_mode_str[] = { 82 + [COUNTER_COUNT_MODE_NORMAL] = "normal", 83 + [COUNTER_COUNT_MODE_RANGE_LIMIT] = "range limit", 84 + [COUNTER_COUNT_MODE_NON_RECYCLE] = "non-recycle", 85 + [COUNTER_COUNT_MODE_MODULO_N] = "modulo-n" 86 + }; 87 + 88 + static ssize_t counter_comp_u8_show(struct device *dev, 89 + struct device_attribute *attr, char *buf) 90 + { 91 + const struct counter_attribute *const a = to_counter_attribute(attr); 92 + struct counter_device *const counter = dev_get_drvdata(dev); 93 + int err; 94 + u8 data = 0; 95 + 96 + switch (a->scope) { 97 + case COUNTER_SCOPE_DEVICE: 98 + err = a->comp.device_u8_read(counter, &data); 99 + break; 100 + case COUNTER_SCOPE_SIGNAL: 101 + err = a->comp.signal_u8_read(counter, a->parent, &data); 102 + break; 103 + case COUNTER_SCOPE_COUNT: 104 + err = a->comp.count_u8_read(counter, a->parent, &data); 105 + break; 106 + default: 107 + return -EINVAL; 108 + } 109 + if (err < 0) 110 + return err; 111 + 112 + if (a->comp.type == COUNTER_COMP_BOOL) 113 + /* data should already be boolean but ensure just to be safe */ 114 + data = !!data; 115 + 116 + return sprintf(buf, "%u\n", (unsigned int)data); 117 + } 118 + 119 + static ssize_t counter_comp_u8_store(struct device *dev, 120 + struct device_attribute *attr, 121 + const char *buf, size_t len) 122 + { 123 + const struct counter_attribute *const a = to_counter_attribute(attr); 124 + struct counter_device *const counter = dev_get_drvdata(dev); 125 + int err; 126 + bool bool_data = 0; 127 + u8 data = 0; 128 + 129 + if (a->comp.type == COUNTER_COMP_BOOL) { 130 + err = kstrtobool(buf, &bool_data); 131 + data = bool_data; 132 + } else 133 + err = kstrtou8(buf, 0, &data); 134 + if (err < 0) 135 + return err; 136 + 137 + switch (a->scope) { 138 + case COUNTER_SCOPE_DEVICE: 139 + err = a->comp.device_u8_write(counter, data); 140 + break; 141 + case COUNTER_SCOPE_SIGNAL: 142 + err = a->comp.signal_u8_write(counter, a->parent, data); 143 + break; 144 + case COUNTER_SCOPE_COUNT: 145 + err = a->comp.count_u8_write(counter, a->parent, data); 146 + break; 147 + default: 148 + return -EINVAL; 149 + } 150 + if (err < 0) 151 + return err; 152 + 153 + return len; 154 + } 155 + 156 + static ssize_t counter_comp_u32_show(struct device *dev, 157 + struct device_attribute *attr, char *buf) 158 + { 159 + const struct counter_attribute *const a = to_counter_attribute(attr); 160 + struct counter_device *const counter = dev_get_drvdata(dev); 161 + const struct counter_available *const avail = a->comp.priv; 162 + int err; 163 + u32 data = 0; 164 + 165 + switch (a->scope) { 166 + case COUNTER_SCOPE_DEVICE: 167 + err = a->comp.device_u32_read(counter, &data); 168 + break; 169 + case COUNTER_SCOPE_SIGNAL: 170 + err = a->comp.signal_u32_read(counter, a->parent, &data); 171 + break; 172 + case COUNTER_SCOPE_COUNT: 173 + if (a->comp.type == COUNTER_COMP_SYNAPSE_ACTION) 174 + err = a->comp.action_read(counter, a->parent, 175 + a->comp.priv, &data); 176 + else 177 + err = a->comp.count_u32_read(counter, a->parent, &data); 178 + break; 179 + default: 180 + return -EINVAL; 181 + } 182 + if (err < 0) 183 + return err; 184 + 185 + switch (a->comp.type) { 186 + case COUNTER_COMP_FUNCTION: 187 + return sysfs_emit(buf, "%s\n", counter_function_str[data]); 188 + case COUNTER_COMP_SIGNAL_LEVEL: 189 + return sysfs_emit(buf, "%s\n", counter_signal_value_str[data]); 190 + case COUNTER_COMP_SYNAPSE_ACTION: 191 + return sysfs_emit(buf, "%s\n", counter_synapse_action_str[data]); 192 + case COUNTER_COMP_ENUM: 193 + return sysfs_emit(buf, "%s\n", avail->strs[data]); 194 + case COUNTER_COMP_COUNT_DIRECTION: 195 + return sysfs_emit(buf, "%s\n", counter_count_direction_str[data]); 196 + case COUNTER_COMP_COUNT_MODE: 197 + return sysfs_emit(buf, "%s\n", counter_count_mode_str[data]); 198 + default: 199 + return sprintf(buf, "%u\n", (unsigned int)data); 200 + } 201 + } 202 + 203 + static int counter_find_enum(u32 *const enum_item, const u32 *const enums, 204 + const size_t num_enums, const char *const buf, 205 + const char *const string_array[]) 206 + { 207 + size_t index; 208 + 209 + for (index = 0; index < num_enums; index++) { 210 + *enum_item = enums[index]; 211 + if (sysfs_streq(buf, string_array[*enum_item])) 212 + return 0; 213 + } 214 + 215 + return -EINVAL; 216 + } 217 + 218 + static ssize_t counter_comp_u32_store(struct device *dev, 219 + struct device_attribute *attr, 220 + const char *buf, size_t len) 221 + { 222 + const struct counter_attribute *const a = to_counter_attribute(attr); 223 + struct counter_device *const counter = dev_get_drvdata(dev); 224 + struct counter_count *const count = a->parent; 225 + struct counter_synapse *const synapse = a->comp.priv; 226 + const struct counter_available *const avail = a->comp.priv; 227 + int err; 228 + u32 data = 0; 229 + 230 + switch (a->comp.type) { 231 + case COUNTER_COMP_FUNCTION: 232 + err = counter_find_enum(&data, count->functions_list, 233 + count->num_functions, buf, 234 + counter_function_str); 235 + break; 236 + case COUNTER_COMP_SYNAPSE_ACTION: 237 + err = counter_find_enum(&data, synapse->actions_list, 238 + synapse->num_actions, buf, 239 + counter_synapse_action_str); 240 + break; 241 + case COUNTER_COMP_ENUM: 242 + err = __sysfs_match_string(avail->strs, avail->num_items, buf); 243 + data = err; 244 + break; 245 + case COUNTER_COMP_COUNT_MODE: 246 + err = counter_find_enum(&data, avail->enums, avail->num_items, 247 + buf, counter_count_mode_str); 248 + break; 249 + default: 250 + err = kstrtou32(buf, 0, &data); 251 + break; 252 + } 253 + if (err < 0) 254 + return err; 255 + 256 + switch (a->scope) { 257 + case COUNTER_SCOPE_DEVICE: 258 + err = a->comp.device_u32_write(counter, data); 259 + break; 260 + case COUNTER_SCOPE_SIGNAL: 261 + err = a->comp.signal_u32_write(counter, a->parent, data); 262 + break; 263 + case COUNTER_SCOPE_COUNT: 264 + if (a->comp.type == COUNTER_COMP_SYNAPSE_ACTION) 265 + err = a->comp.action_write(counter, count, synapse, 266 + data); 267 + else 268 + err = a->comp.count_u32_write(counter, count, data); 269 + break; 270 + default: 271 + return -EINVAL; 272 + } 273 + if (err < 0) 274 + return err; 275 + 276 + return len; 277 + } 278 + 279 + static ssize_t counter_comp_u64_show(struct device *dev, 280 + struct device_attribute *attr, char *buf) 281 + { 282 + const struct counter_attribute *const a = to_counter_attribute(attr); 283 + struct counter_device *const counter = dev_get_drvdata(dev); 284 + int err; 285 + u64 data = 0; 286 + 287 + switch (a->scope) { 288 + case COUNTER_SCOPE_DEVICE: 289 + err = a->comp.device_u64_read(counter, &data); 290 + break; 291 + case COUNTER_SCOPE_SIGNAL: 292 + err = a->comp.signal_u64_read(counter, a->parent, &data); 293 + break; 294 + case COUNTER_SCOPE_COUNT: 295 + err = a->comp.count_u64_read(counter, a->parent, &data); 296 + break; 297 + default: 298 + return -EINVAL; 299 + } 300 + if (err < 0) 301 + return err; 302 + 303 + return sprintf(buf, "%llu\n", (unsigned long long)data); 304 + } 305 + 306 + static ssize_t counter_comp_u64_store(struct device *dev, 307 + struct device_attribute *attr, 308 + const char *buf, size_t len) 309 + { 310 + const struct counter_attribute *const a = to_counter_attribute(attr); 311 + struct counter_device *const counter = dev_get_drvdata(dev); 312 + int err; 313 + u64 data = 0; 314 + 315 + err = kstrtou64(buf, 0, &data); 316 + if (err < 0) 317 + return err; 318 + 319 + switch (a->scope) { 320 + case COUNTER_SCOPE_DEVICE: 321 + err = a->comp.device_u64_write(counter, data); 322 + break; 323 + case COUNTER_SCOPE_SIGNAL: 324 + err = a->comp.signal_u64_write(counter, a->parent, data); 325 + break; 326 + case COUNTER_SCOPE_COUNT: 327 + err = a->comp.count_u64_write(counter, a->parent, data); 328 + break; 329 + default: 330 + return -EINVAL; 331 + } 332 + if (err < 0) 333 + return err; 334 + 335 + return len; 336 + } 337 + 338 + static ssize_t enums_available_show(const u32 *const enums, 339 + const size_t num_enums, 340 + const char *const strs[], char *buf) 341 + { 342 + size_t len = 0; 343 + size_t index; 344 + 345 + for (index = 0; index < num_enums; index++) 346 + len += sysfs_emit_at(buf, len, "%s\n", strs[enums[index]]); 347 + 348 + return len; 349 + } 350 + 351 + static ssize_t strs_available_show(const struct counter_available *const avail, 352 + char *buf) 353 + { 354 + size_t len = 0; 355 + size_t index; 356 + 357 + for (index = 0; index < avail->num_items; index++) 358 + len += sysfs_emit_at(buf, len, "%s\n", avail->strs[index]); 359 + 360 + return len; 361 + } 362 + 363 + static ssize_t counter_comp_available_show(struct device *dev, 364 + struct device_attribute *attr, 365 + char *buf) 366 + { 367 + const struct counter_attribute *const a = to_counter_attribute(attr); 368 + const struct counter_count *const count = a->parent; 369 + const struct counter_synapse *const synapse = a->comp.priv; 370 + const struct counter_available *const avail = a->comp.priv; 371 + 372 + switch (a->comp.type) { 373 + case COUNTER_COMP_FUNCTION: 374 + return enums_available_show(count->functions_list, 375 + count->num_functions, 376 + counter_function_str, buf); 377 + case COUNTER_COMP_SYNAPSE_ACTION: 378 + return enums_available_show(synapse->actions_list, 379 + synapse->num_actions, 380 + counter_synapse_action_str, buf); 381 + case COUNTER_COMP_ENUM: 382 + return strs_available_show(avail, buf); 383 + case COUNTER_COMP_COUNT_MODE: 384 + return enums_available_show(avail->enums, avail->num_items, 385 + counter_count_mode_str, buf); 386 + default: 387 + return -EINVAL; 388 + } 389 + } 390 + 391 + static int counter_avail_attr_create(struct device *const dev, 392 + struct counter_attribute_group *const group, 393 + const struct counter_comp *const comp, void *const parent) 394 + { 395 + struct counter_attribute *counter_attr; 396 + struct device_attribute *dev_attr; 397 + 398 + counter_attr = devm_kzalloc(dev, sizeof(*counter_attr), GFP_KERNEL); 399 + if (!counter_attr) 400 + return -ENOMEM; 401 + 402 + /* Configure Counter attribute */ 403 + counter_attr->comp.type = comp->type; 404 + counter_attr->comp.priv = comp->priv; 405 + counter_attr->parent = parent; 406 + 407 + /* Initialize sysfs attribute */ 408 + dev_attr = &counter_attr->dev_attr; 409 + sysfs_attr_init(&dev_attr->attr); 410 + 411 + /* Configure device attribute */ 412 + dev_attr->attr.name = devm_kasprintf(dev, GFP_KERNEL, "%s_available", 413 + comp->name); 414 + if (!dev_attr->attr.name) 415 + return -ENOMEM; 416 + dev_attr->attr.mode = 0444; 417 + dev_attr->show = counter_comp_available_show; 418 + 419 + /* Store list node */ 420 + list_add(&counter_attr->l, &group->attr_list); 421 + group->num_attr++; 422 + 423 + return 0; 424 + } 425 + 426 + static int counter_attr_create(struct device *const dev, 427 + struct counter_attribute_group *const group, 428 + const struct counter_comp *const comp, 429 + const enum counter_scope scope, 430 + void *const parent) 431 + { 432 + struct counter_attribute *counter_attr; 433 + struct device_attribute *dev_attr; 434 + 435 + counter_attr = devm_kzalloc(dev, sizeof(*counter_attr), GFP_KERNEL); 436 + if (!counter_attr) 437 + return -ENOMEM; 438 + 439 + /* Configure Counter attribute */ 440 + counter_attr->comp = *comp; 441 + counter_attr->scope = scope; 442 + counter_attr->parent = parent; 443 + 444 + /* Configure device attribute */ 445 + dev_attr = &counter_attr->dev_attr; 446 + sysfs_attr_init(&dev_attr->attr); 447 + dev_attr->attr.name = comp->name; 448 + switch (comp->type) { 449 + case COUNTER_COMP_U8: 450 + case COUNTER_COMP_BOOL: 451 + if (comp->device_u8_read) { 452 + dev_attr->attr.mode |= 0444; 453 + dev_attr->show = counter_comp_u8_show; 454 + } 455 + if (comp->device_u8_write) { 456 + dev_attr->attr.mode |= 0200; 457 + dev_attr->store = counter_comp_u8_store; 458 + } 459 + break; 460 + case COUNTER_COMP_SIGNAL_LEVEL: 461 + case COUNTER_COMP_FUNCTION: 462 + case COUNTER_COMP_SYNAPSE_ACTION: 463 + case COUNTER_COMP_ENUM: 464 + case COUNTER_COMP_COUNT_DIRECTION: 465 + case COUNTER_COMP_COUNT_MODE: 466 + if (comp->device_u32_read) { 467 + dev_attr->attr.mode |= 0444; 468 + dev_attr->show = counter_comp_u32_show; 469 + } 470 + if (comp->device_u32_write) { 471 + dev_attr->attr.mode |= 0200; 472 + dev_attr->store = counter_comp_u32_store; 473 + } 474 + break; 475 + case COUNTER_COMP_U64: 476 + if (comp->device_u64_read) { 477 + dev_attr->attr.mode |= 0444; 478 + dev_attr->show = counter_comp_u64_show; 479 + } 480 + if (comp->device_u64_write) { 481 + dev_attr->attr.mode |= 0200; 482 + dev_attr->store = counter_comp_u64_store; 483 + } 484 + break; 485 + default: 486 + return -EINVAL; 487 + } 488 + 489 + /* Store list node */ 490 + list_add(&counter_attr->l, &group->attr_list); 491 + group->num_attr++; 492 + 493 + /* Create "*_available" attribute if needed */ 494 + switch (comp->type) { 495 + case COUNTER_COMP_FUNCTION: 496 + case COUNTER_COMP_SYNAPSE_ACTION: 497 + case COUNTER_COMP_ENUM: 498 + case COUNTER_COMP_COUNT_MODE: 499 + return counter_avail_attr_create(dev, group, comp, parent); 500 + default: 501 + return 0; 502 + } 503 + } 504 + 505 + static ssize_t counter_comp_name_show(struct device *dev, 506 + struct device_attribute *attr, char *buf) 507 + { 508 + return sysfs_emit(buf, "%s\n", to_counter_attribute(attr)->comp.name); 509 + } 510 + 511 + static int counter_name_attr_create(struct device *const dev, 512 + struct counter_attribute_group *const group, 513 + const char *const name) 514 + { 515 + struct counter_attribute *counter_attr; 516 + 517 + counter_attr = devm_kzalloc(dev, sizeof(*counter_attr), GFP_KERNEL); 518 + if (!counter_attr) 519 + return -ENOMEM; 520 + 521 + /* Configure Counter attribute */ 522 + counter_attr->comp.name = name; 523 + 524 + /* Configure device attribute */ 525 + sysfs_attr_init(&counter_attr->dev_attr.attr); 526 + counter_attr->dev_attr.attr.name = "name"; 527 + counter_attr->dev_attr.attr.mode = 0444; 528 + counter_attr->dev_attr.show = counter_comp_name_show; 529 + 530 + /* Store list node */ 531 + list_add(&counter_attr->l, &group->attr_list); 532 + group->num_attr++; 533 + 534 + return 0; 535 + } 536 + 537 + static ssize_t counter_comp_id_show(struct device *dev, 538 + struct device_attribute *attr, char *buf) 539 + { 540 + const size_t id = (size_t)to_counter_attribute(attr)->comp.priv; 541 + 542 + return sprintf(buf, "%zu\n", id); 543 + } 544 + 545 + static int counter_comp_id_attr_create(struct device *const dev, 546 + struct counter_attribute_group *const group, 547 + const char *name, const size_t id) 548 + { 549 + struct counter_attribute *counter_attr; 550 + 551 + /* Allocate Counter attribute */ 552 + counter_attr = devm_kzalloc(dev, sizeof(*counter_attr), GFP_KERNEL); 553 + if (!counter_attr) 554 + return -ENOMEM; 555 + 556 + /* Generate component ID name */ 557 + name = devm_kasprintf(dev, GFP_KERNEL, "%s_component_id", name); 558 + if (!name) 559 + return -ENOMEM; 560 + 561 + /* Configure Counter attribute */ 562 + counter_attr->comp.priv = (void *)id; 563 + 564 + /* Configure device attribute */ 565 + sysfs_attr_init(&counter_attr->dev_attr.attr); 566 + counter_attr->dev_attr.attr.name = name; 567 + counter_attr->dev_attr.attr.mode = 0444; 568 + counter_attr->dev_attr.show = counter_comp_id_show; 569 + 570 + /* Store list node */ 571 + list_add(&counter_attr->l, &group->attr_list); 572 + group->num_attr++; 573 + 574 + return 0; 575 + } 576 + 577 + static struct counter_comp counter_signal_comp = { 578 + .type = COUNTER_COMP_SIGNAL_LEVEL, 579 + .name = "signal", 580 + }; 581 + 582 + static int counter_signal_attrs_create(struct counter_device *const counter, 583 + struct counter_attribute_group *const cattr_group, 584 + struct counter_signal *const signal) 585 + { 586 + const enum counter_scope scope = COUNTER_SCOPE_SIGNAL; 587 + struct device *const dev = &counter->dev; 588 + int err; 589 + struct counter_comp comp; 590 + size_t i; 591 + struct counter_comp *ext; 592 + 593 + /* Create main Signal attribute */ 594 + comp = counter_signal_comp; 595 + comp.signal_u32_read = counter->ops->signal_read; 596 + err = counter_attr_create(dev, cattr_group, &comp, scope, signal); 597 + if (err < 0) 598 + return err; 599 + 600 + /* Create Signal name attribute */ 601 + err = counter_name_attr_create(dev, cattr_group, signal->name); 602 + if (err < 0) 603 + return err; 604 + 605 + /* Create an attribute for each extension */ 606 + for (i = 0; i < signal->num_ext; i++) { 607 + ext = &signal->ext[i]; 608 + 609 + err = counter_attr_create(dev, cattr_group, ext, scope, signal); 610 + if (err < 0) 611 + return err; 612 + 613 + err = counter_comp_id_attr_create(dev, cattr_group, ext->name, 614 + i); 615 + if (err < 0) 616 + return err; 617 + } 618 + 619 + return 0; 620 + } 621 + 622 + static int counter_sysfs_signals_add(struct counter_device *const counter, 623 + struct counter_attribute_group *const groups) 624 + { 625 + size_t i; 626 + int err; 627 + 628 + /* Add each Signal */ 629 + for (i = 0; i < counter->num_signals; i++) { 630 + /* Generate Signal attribute directory name */ 631 + groups[i].name = devm_kasprintf(&counter->dev, GFP_KERNEL, 632 + "signal%zu", i); 633 + if (!groups[i].name) 634 + return -ENOMEM; 635 + 636 + /* Create all attributes associated with Signal */ 637 + err = counter_signal_attrs_create(counter, groups + i, 638 + counter->signals + i); 639 + if (err < 0) 640 + return err; 641 + } 642 + 643 + return 0; 644 + } 645 + 646 + static int counter_sysfs_synapses_add(struct counter_device *const counter, 647 + struct counter_attribute_group *const group, 648 + struct counter_count *const count) 649 + { 650 + size_t i; 651 + 652 + /* Add each Synapse */ 653 + for (i = 0; i < count->num_synapses; i++) { 654 + struct device *const dev = &counter->dev; 655 + struct counter_synapse *synapse; 656 + size_t id; 657 + struct counter_comp comp; 658 + int err; 659 + 660 + synapse = count->synapses + i; 661 + 662 + /* Generate Synapse action name */ 663 + id = synapse->signal - counter->signals; 664 + comp.name = devm_kasprintf(dev, GFP_KERNEL, "signal%zu_action", 665 + id); 666 + if (!comp.name) 667 + return -ENOMEM; 668 + 669 + /* Create action attribute */ 670 + comp.type = COUNTER_COMP_SYNAPSE_ACTION; 671 + comp.action_read = counter->ops->action_read; 672 + comp.action_write = counter->ops->action_write; 673 + comp.priv = synapse; 674 + err = counter_attr_create(dev, group, &comp, 675 + COUNTER_SCOPE_COUNT, count); 676 + if (err < 0) 677 + return err; 678 + 679 + /* Create Synapse component ID attribute */ 680 + err = counter_comp_id_attr_create(dev, group, comp.name, i); 681 + if (err < 0) 682 + return err; 683 + } 684 + 685 + return 0; 686 + } 687 + 688 + static struct counter_comp counter_count_comp = 689 + COUNTER_COMP_COUNT_U64("count", NULL, NULL); 690 + 691 + static struct counter_comp counter_function_comp = { 692 + .type = COUNTER_COMP_FUNCTION, 693 + .name = "function", 694 + }; 695 + 696 + static int counter_count_attrs_create(struct counter_device *const counter, 697 + struct counter_attribute_group *const cattr_group, 698 + struct counter_count *const count) 699 + { 700 + const enum counter_scope scope = COUNTER_SCOPE_COUNT; 701 + struct device *const dev = &counter->dev; 702 + int err; 703 + struct counter_comp comp; 704 + size_t i; 705 + struct counter_comp *ext; 706 + 707 + /* Create main Count attribute */ 708 + comp = counter_count_comp; 709 + comp.count_u64_read = counter->ops->count_read; 710 + comp.count_u64_write = counter->ops->count_write; 711 + err = counter_attr_create(dev, cattr_group, &comp, scope, count); 712 + if (err < 0) 713 + return err; 714 + 715 + /* Create Count name attribute */ 716 + err = counter_name_attr_create(dev, cattr_group, count->name); 717 + if (err < 0) 718 + return err; 719 + 720 + /* Create Count function attribute */ 721 + comp = counter_function_comp; 722 + comp.count_u32_read = counter->ops->function_read; 723 + comp.count_u32_write = counter->ops->function_write; 724 + err = counter_attr_create(dev, cattr_group, &comp, scope, count); 725 + if (err < 0) 726 + return err; 727 + 728 + /* Create an attribute for each extension */ 729 + for (i = 0; i < count->num_ext; i++) { 730 + ext = &count->ext[i]; 731 + 732 + err = counter_attr_create(dev, cattr_group, ext, scope, count); 733 + if (err < 0) 734 + return err; 735 + 736 + err = counter_comp_id_attr_create(dev, cattr_group, ext->name, 737 + i); 738 + if (err < 0) 739 + return err; 740 + } 741 + 742 + return 0; 743 + } 744 + 745 + static int counter_sysfs_counts_add(struct counter_device *const counter, 746 + struct counter_attribute_group *const groups) 747 + { 748 + size_t i; 749 + struct counter_count *count; 750 + int err; 751 + 752 + /* Add each Count */ 753 + for (i = 0; i < counter->num_counts; i++) { 754 + count = counter->counts + i; 755 + 756 + /* Generate Count attribute directory name */ 757 + groups[i].name = devm_kasprintf(&counter->dev, GFP_KERNEL, 758 + "count%zu", i); 759 + if (!groups[i].name) 760 + return -ENOMEM; 761 + 762 + /* Add sysfs attributes of the Synapses */ 763 + err = counter_sysfs_synapses_add(counter, groups + i, count); 764 + if (err < 0) 765 + return err; 766 + 767 + /* Create all attributes associated with Count */ 768 + err = counter_count_attrs_create(counter, groups + i, count); 769 + if (err < 0) 770 + return err; 771 + } 772 + 773 + return 0; 774 + } 775 + 776 + static int counter_num_signals_read(struct counter_device *counter, u8 *val) 777 + { 778 + *val = counter->num_signals; 779 + return 0; 780 + } 781 + 782 + static int counter_num_counts_read(struct counter_device *counter, u8 *val) 783 + { 784 + *val = counter->num_counts; 785 + return 0; 786 + } 787 + 788 + static int counter_events_queue_size_read(struct counter_device *counter, 789 + u64 *val) 790 + { 791 + *val = kfifo_size(&counter->events); 792 + return 0; 793 + } 794 + 795 + static int counter_events_queue_size_write(struct counter_device *counter, 796 + u64 val) 797 + { 798 + DECLARE_KFIFO_PTR(events, struct counter_event); 799 + int err = 0; 800 + 801 + /* Ensure chrdev is not opened more than 1 at a time */ 802 + if (!atomic_add_unless(&counter->chrdev_lock, 1, 1)) 803 + return -EBUSY; 804 + 805 + /* Allocate new events queue */ 806 + err = kfifo_alloc(&events, val, GFP_KERNEL); 807 + if (err) 808 + goto exit_early; 809 + 810 + /* Swap in new events queue */ 811 + kfifo_free(&counter->events); 812 + counter->events.kfifo = events.kfifo; 813 + 814 + exit_early: 815 + atomic_dec(&counter->chrdev_lock); 816 + 817 + return err; 818 + } 819 + 820 + static struct counter_comp counter_num_signals_comp = 821 + COUNTER_COMP_DEVICE_U8("num_signals", counter_num_signals_read, NULL); 822 + 823 + static struct counter_comp counter_num_counts_comp = 824 + COUNTER_COMP_DEVICE_U8("num_counts", counter_num_counts_read, NULL); 825 + 826 + static struct counter_comp counter_events_queue_size_comp = 827 + COUNTER_COMP_DEVICE_U64("events_queue_size", 828 + counter_events_queue_size_read, 829 + counter_events_queue_size_write); 830 + 831 + static int counter_sysfs_attr_add(struct counter_device *const counter, 832 + struct counter_attribute_group *cattr_group) 833 + { 834 + const enum counter_scope scope = COUNTER_SCOPE_DEVICE; 835 + struct device *const dev = &counter->dev; 836 + int err; 837 + size_t i; 838 + struct counter_comp *ext; 839 + 840 + /* Add Signals sysfs attributes */ 841 + err = counter_sysfs_signals_add(counter, cattr_group); 842 + if (err < 0) 843 + return err; 844 + cattr_group += counter->num_signals; 845 + 846 + /* Add Counts sysfs attributes */ 847 + err = counter_sysfs_counts_add(counter, cattr_group); 848 + if (err < 0) 849 + return err; 850 + cattr_group += counter->num_counts; 851 + 852 + /* Create name attribute */ 853 + err = counter_name_attr_create(dev, cattr_group, counter->name); 854 + if (err < 0) 855 + return err; 856 + 857 + /* Create num_signals attribute */ 858 + err = counter_attr_create(dev, cattr_group, &counter_num_signals_comp, 859 + scope, NULL); 860 + if (err < 0) 861 + return err; 862 + 863 + /* Create num_counts attribute */ 864 + err = counter_attr_create(dev, cattr_group, &counter_num_counts_comp, 865 + scope, NULL); 866 + if (err < 0) 867 + return err; 868 + 869 + /* Create events_queue_size attribute */ 870 + err = counter_attr_create(dev, cattr_group, 871 + &counter_events_queue_size_comp, scope, NULL); 872 + if (err < 0) 873 + return err; 874 + 875 + /* Create an attribute for each extension */ 876 + for (i = 0; i < counter->num_ext; i++) { 877 + ext = &counter->ext[i]; 878 + 879 + err = counter_attr_create(dev, cattr_group, ext, scope, NULL); 880 + if (err < 0) 881 + return err; 882 + 883 + err = counter_comp_id_attr_create(dev, cattr_group, ext->name, 884 + i); 885 + if (err < 0) 886 + return err; 887 + } 888 + 889 + return 0; 890 + } 891 + 892 + /** 893 + * counter_sysfs_add - Adds Counter sysfs attributes to the device structure 894 + * @counter: Pointer to the Counter device structure 895 + * 896 + * Counter sysfs attributes are created and added to the respective device 897 + * structure for later registration to the system. Resource-managed memory 898 + * allocation is performed by this function, and this memory should be freed 899 + * when no longer needed (automatically by a device_unregister call, or 900 + * manually by a devres_release_all call). 901 + */ 902 + int counter_sysfs_add(struct counter_device *const counter) 903 + { 904 + struct device *const dev = &counter->dev; 905 + const size_t num_groups = counter->num_signals + counter->num_counts + 1; 906 + struct counter_attribute_group *cattr_groups; 907 + size_t i, j; 908 + int err; 909 + struct attribute_group *groups; 910 + struct counter_attribute *p; 911 + 912 + /* Allocate space for attribute groups (signals, counts, and ext) */ 913 + cattr_groups = devm_kcalloc(dev, num_groups, sizeof(*cattr_groups), 914 + GFP_KERNEL); 915 + if (!cattr_groups) 916 + return -ENOMEM; 917 + 918 + /* Initialize attribute lists */ 919 + for (i = 0; i < num_groups; i++) 920 + INIT_LIST_HEAD(&cattr_groups[i].attr_list); 921 + 922 + /* Add Counter device sysfs attributes */ 923 + err = counter_sysfs_attr_add(counter, cattr_groups); 924 + if (err < 0) 925 + return err; 926 + 927 + /* Allocate attribute group pointers for association with device */ 928 + dev->groups = devm_kcalloc(dev, num_groups + 1, sizeof(*dev->groups), 929 + GFP_KERNEL); 930 + if (!dev->groups) 931 + return -ENOMEM; 932 + 933 + /* Allocate space for attribute groups */ 934 + groups = devm_kcalloc(dev, num_groups, sizeof(*groups), GFP_KERNEL); 935 + if (!groups) 936 + return -ENOMEM; 937 + 938 + /* Prepare each group of attributes for association */ 939 + for (i = 0; i < num_groups; i++) { 940 + groups[i].name = cattr_groups[i].name; 941 + 942 + /* Allocate space for attribute pointers */ 943 + groups[i].attrs = devm_kcalloc(dev, 944 + cattr_groups[i].num_attr + 1, 945 + sizeof(*groups[i].attrs), 946 + GFP_KERNEL); 947 + if (!groups[i].attrs) 948 + return -ENOMEM; 949 + 950 + /* Add attribute pointers to attribute group */ 951 + j = 0; 952 + list_for_each_entry(p, &cattr_groups[i].attr_list, l) 953 + groups[i].attrs[j++] = &p->dev_attr.attr; 954 + 955 + /* Associate attribute group */ 956 + dev->groups[i] = &groups[i]; 957 + } 958 + 959 + return 0; 960 + }
+13
drivers/counter/counter-sysfs.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Counter sysfs interface 4 + * Copyright (C) 2020 William Breathitt Gray 5 + */ 6 + #ifndef _COUNTER_SYSFS_H_ 7 + #define _COUNTER_SYSFS_H_ 8 + 9 + #include <linux/counter.h> 10 + 11 + int counter_sysfs_add(struct counter_device *const counter); 12 + 13 + #endif /* _COUNTER_SYSFS_H_ */
-1496
drivers/counter/counter.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* 3 - * Generic Counter interface 4 - * Copyright (C) 2018 William Breathitt Gray 5 - */ 6 - #include <linux/counter.h> 7 - #include <linux/device.h> 8 - #include <linux/err.h> 9 - #include <linux/export.h> 10 - #include <linux/fs.h> 11 - #include <linux/gfp.h> 12 - #include <linux/idr.h> 13 - #include <linux/init.h> 14 - #include <linux/kernel.h> 15 - #include <linux/list.h> 16 - #include <linux/module.h> 17 - #include <linux/printk.h> 18 - #include <linux/slab.h> 19 - #include <linux/string.h> 20 - #include <linux/sysfs.h> 21 - #include <linux/types.h> 22 - 23 - const char *const counter_count_direction_str[2] = { 24 - [COUNTER_COUNT_DIRECTION_FORWARD] = "forward", 25 - [COUNTER_COUNT_DIRECTION_BACKWARD] = "backward" 26 - }; 27 - EXPORT_SYMBOL_GPL(counter_count_direction_str); 28 - 29 - const char *const counter_count_mode_str[4] = { 30 - [COUNTER_COUNT_MODE_NORMAL] = "normal", 31 - [COUNTER_COUNT_MODE_RANGE_LIMIT] = "range limit", 32 - [COUNTER_COUNT_MODE_NON_RECYCLE] = "non-recycle", 33 - [COUNTER_COUNT_MODE_MODULO_N] = "modulo-n" 34 - }; 35 - EXPORT_SYMBOL_GPL(counter_count_mode_str); 36 - 37 - ssize_t counter_signal_enum_read(struct counter_device *counter, 38 - struct counter_signal *signal, void *priv, 39 - char *buf) 40 - { 41 - const struct counter_signal_enum_ext *const e = priv; 42 - int err; 43 - size_t index; 44 - 45 - if (!e->get) 46 - return -EINVAL; 47 - 48 - err = e->get(counter, signal, &index); 49 - if (err) 50 - return err; 51 - 52 - if (index >= e->num_items) 53 - return -EINVAL; 54 - 55 - return sprintf(buf, "%s\n", e->items[index]); 56 - } 57 - EXPORT_SYMBOL_GPL(counter_signal_enum_read); 58 - 59 - ssize_t counter_signal_enum_write(struct counter_device *counter, 60 - struct counter_signal *signal, void *priv, 61 - const char *buf, size_t len) 62 - { 63 - const struct counter_signal_enum_ext *const e = priv; 64 - ssize_t index; 65 - int err; 66 - 67 - if (!e->set) 68 - return -EINVAL; 69 - 70 - index = __sysfs_match_string(e->items, e->num_items, buf); 71 - if (index < 0) 72 - return index; 73 - 74 - err = e->set(counter, signal, index); 75 - if (err) 76 - return err; 77 - 78 - return len; 79 - } 80 - EXPORT_SYMBOL_GPL(counter_signal_enum_write); 81 - 82 - ssize_t counter_signal_enum_available_read(struct counter_device *counter, 83 - struct counter_signal *signal, 84 - void *priv, char *buf) 85 - { 86 - const struct counter_signal_enum_ext *const e = priv; 87 - size_t i; 88 - size_t len = 0; 89 - 90 - if (!e->num_items) 91 - return 0; 92 - 93 - for (i = 0; i < e->num_items; i++) 94 - len += sprintf(buf + len, "%s\n", e->items[i]); 95 - 96 - return len; 97 - } 98 - EXPORT_SYMBOL_GPL(counter_signal_enum_available_read); 99 - 100 - ssize_t counter_count_enum_read(struct counter_device *counter, 101 - struct counter_count *count, void *priv, 102 - char *buf) 103 - { 104 - const struct counter_count_enum_ext *const e = priv; 105 - int err; 106 - size_t index; 107 - 108 - if (!e->get) 109 - return -EINVAL; 110 - 111 - err = e->get(counter, count, &index); 112 - if (err) 113 - return err; 114 - 115 - if (index >= e->num_items) 116 - return -EINVAL; 117 - 118 - return sprintf(buf, "%s\n", e->items[index]); 119 - } 120 - EXPORT_SYMBOL_GPL(counter_count_enum_read); 121 - 122 - ssize_t counter_count_enum_write(struct counter_device *counter, 123 - struct counter_count *count, void *priv, 124 - const char *buf, size_t len) 125 - { 126 - const struct counter_count_enum_ext *const e = priv; 127 - ssize_t index; 128 - int err; 129 - 130 - if (!e->set) 131 - return -EINVAL; 132 - 133 - index = __sysfs_match_string(e->items, e->num_items, buf); 134 - if (index < 0) 135 - return index; 136 - 137 - err = e->set(counter, count, index); 138 - if (err) 139 - return err; 140 - 141 - return len; 142 - } 143 - EXPORT_SYMBOL_GPL(counter_count_enum_write); 144 - 145 - ssize_t counter_count_enum_available_read(struct counter_device *counter, 146 - struct counter_count *count, 147 - void *priv, char *buf) 148 - { 149 - const struct counter_count_enum_ext *const e = priv; 150 - size_t i; 151 - size_t len = 0; 152 - 153 - if (!e->num_items) 154 - return 0; 155 - 156 - for (i = 0; i < e->num_items; i++) 157 - len += sprintf(buf + len, "%s\n", e->items[i]); 158 - 159 - return len; 160 - } 161 - EXPORT_SYMBOL_GPL(counter_count_enum_available_read); 162 - 163 - ssize_t counter_device_enum_read(struct counter_device *counter, void *priv, 164 - char *buf) 165 - { 166 - const struct counter_device_enum_ext *const e = priv; 167 - int err; 168 - size_t index; 169 - 170 - if (!e->get) 171 - return -EINVAL; 172 - 173 - err = e->get(counter, &index); 174 - if (err) 175 - return err; 176 - 177 - if (index >= e->num_items) 178 - return -EINVAL; 179 - 180 - return sprintf(buf, "%s\n", e->items[index]); 181 - } 182 - EXPORT_SYMBOL_GPL(counter_device_enum_read); 183 - 184 - ssize_t counter_device_enum_write(struct counter_device *counter, void *priv, 185 - const char *buf, size_t len) 186 - { 187 - const struct counter_device_enum_ext *const e = priv; 188 - ssize_t index; 189 - int err; 190 - 191 - if (!e->set) 192 - return -EINVAL; 193 - 194 - index = __sysfs_match_string(e->items, e->num_items, buf); 195 - if (index < 0) 196 - return index; 197 - 198 - err = e->set(counter, index); 199 - if (err) 200 - return err; 201 - 202 - return len; 203 - } 204 - EXPORT_SYMBOL_GPL(counter_device_enum_write); 205 - 206 - ssize_t counter_device_enum_available_read(struct counter_device *counter, 207 - void *priv, char *buf) 208 - { 209 - const struct counter_device_enum_ext *const e = priv; 210 - size_t i; 211 - size_t len = 0; 212 - 213 - if (!e->num_items) 214 - return 0; 215 - 216 - for (i = 0; i < e->num_items; i++) 217 - len += sprintf(buf + len, "%s\n", e->items[i]); 218 - 219 - return len; 220 - } 221 - EXPORT_SYMBOL_GPL(counter_device_enum_available_read); 222 - 223 - struct counter_attr_parm { 224 - struct counter_device_attr_group *group; 225 - const char *prefix; 226 - const char *name; 227 - ssize_t (*show)(struct device *dev, struct device_attribute *attr, 228 - char *buf); 229 - ssize_t (*store)(struct device *dev, struct device_attribute *attr, 230 - const char *buf, size_t len); 231 - void *component; 232 - }; 233 - 234 - struct counter_device_attr { 235 - struct device_attribute dev_attr; 236 - struct list_head l; 237 - void *component; 238 - }; 239 - 240 - static int counter_attribute_create(const struct counter_attr_parm *const parm) 241 - { 242 - struct counter_device_attr *counter_attr; 243 - struct device_attribute *dev_attr; 244 - int err; 245 - struct list_head *const attr_list = &parm->group->attr_list; 246 - 247 - /* Allocate a Counter device attribute */ 248 - counter_attr = kzalloc(sizeof(*counter_attr), GFP_KERNEL); 249 - if (!counter_attr) 250 - return -ENOMEM; 251 - dev_attr = &counter_attr->dev_attr; 252 - 253 - sysfs_attr_init(&dev_attr->attr); 254 - 255 - /* Configure device attribute */ 256 - dev_attr->attr.name = kasprintf(GFP_KERNEL, "%s%s", parm->prefix, 257 - parm->name); 258 - if (!dev_attr->attr.name) { 259 - err = -ENOMEM; 260 - goto err_free_counter_attr; 261 - } 262 - if (parm->show) { 263 - dev_attr->attr.mode |= 0444; 264 - dev_attr->show = parm->show; 265 - } 266 - if (parm->store) { 267 - dev_attr->attr.mode |= 0200; 268 - dev_attr->store = parm->store; 269 - } 270 - 271 - /* Store associated Counter component with attribute */ 272 - counter_attr->component = parm->component; 273 - 274 - /* Keep track of the attribute for later cleanup */ 275 - list_add(&counter_attr->l, attr_list); 276 - parm->group->num_attr++; 277 - 278 - return 0; 279 - 280 - err_free_counter_attr: 281 - kfree(counter_attr); 282 - return err; 283 - } 284 - 285 - #define to_counter_attr(_dev_attr) \ 286 - container_of(_dev_attr, struct counter_device_attr, dev_attr) 287 - 288 - struct counter_signal_unit { 289 - struct counter_signal *signal; 290 - }; 291 - 292 - static const char *const counter_signal_level_str[] = { 293 - [COUNTER_SIGNAL_LEVEL_LOW] = "low", 294 - [COUNTER_SIGNAL_LEVEL_HIGH] = "high" 295 - }; 296 - 297 - static ssize_t counter_signal_show(struct device *dev, 298 - struct device_attribute *attr, char *buf) 299 - { 300 - struct counter_device *const counter = dev_get_drvdata(dev); 301 - const struct counter_device_attr *const devattr = to_counter_attr(attr); 302 - const struct counter_signal_unit *const component = devattr->component; 303 - struct counter_signal *const signal = component->signal; 304 - int err; 305 - enum counter_signal_level level; 306 - 307 - err = counter->ops->signal_read(counter, signal, &level); 308 - if (err) 309 - return err; 310 - 311 - return sprintf(buf, "%s\n", counter_signal_level_str[level]); 312 - } 313 - 314 - struct counter_name_unit { 315 - const char *name; 316 - }; 317 - 318 - static ssize_t counter_device_attr_name_show(struct device *dev, 319 - struct device_attribute *attr, 320 - char *buf) 321 - { 322 - const struct counter_name_unit *const comp = to_counter_attr(attr)->component; 323 - 324 - return sprintf(buf, "%s\n", comp->name); 325 - } 326 - 327 - static int counter_name_attribute_create( 328 - struct counter_device_attr_group *const group, 329 - const char *const name) 330 - { 331 - struct counter_name_unit *name_comp; 332 - struct counter_attr_parm parm; 333 - int err; 334 - 335 - /* Skip if no name */ 336 - if (!name) 337 - return 0; 338 - 339 - /* Allocate name attribute component */ 340 - name_comp = kmalloc(sizeof(*name_comp), GFP_KERNEL); 341 - if (!name_comp) 342 - return -ENOMEM; 343 - name_comp->name = name; 344 - 345 - /* Allocate Signal name attribute */ 346 - parm.group = group; 347 - parm.prefix = ""; 348 - parm.name = "name"; 349 - parm.show = counter_device_attr_name_show; 350 - parm.store = NULL; 351 - parm.component = name_comp; 352 - err = counter_attribute_create(&parm); 353 - if (err) 354 - goto err_free_name_comp; 355 - 356 - return 0; 357 - 358 - err_free_name_comp: 359 - kfree(name_comp); 360 - return err; 361 - } 362 - 363 - struct counter_signal_ext_unit { 364 - struct counter_signal *signal; 365 - const struct counter_signal_ext *ext; 366 - }; 367 - 368 - static ssize_t counter_signal_ext_show(struct device *dev, 369 - struct device_attribute *attr, char *buf) 370 - { 371 - const struct counter_device_attr *const devattr = to_counter_attr(attr); 372 - const struct counter_signal_ext_unit *const comp = devattr->component; 373 - const struct counter_signal_ext *const ext = comp->ext; 374 - 375 - return ext->read(dev_get_drvdata(dev), comp->signal, ext->priv, buf); 376 - } 377 - 378 - static ssize_t counter_signal_ext_store(struct device *dev, 379 - struct device_attribute *attr, 380 - const char *buf, size_t len) 381 - { 382 - const struct counter_device_attr *const devattr = to_counter_attr(attr); 383 - const struct counter_signal_ext_unit *const comp = devattr->component; 384 - const struct counter_signal_ext *const ext = comp->ext; 385 - 386 - return ext->write(dev_get_drvdata(dev), comp->signal, ext->priv, buf, 387 - len); 388 - } 389 - 390 - static void counter_device_attr_list_free(struct list_head *attr_list) 391 - { 392 - struct counter_device_attr *p, *n; 393 - 394 - list_for_each_entry_safe(p, n, attr_list, l) { 395 - /* free attribute name and associated component memory */ 396 - kfree(p->dev_attr.attr.name); 397 - kfree(p->component); 398 - list_del(&p->l); 399 - kfree(p); 400 - } 401 - } 402 - 403 - static int counter_signal_ext_register( 404 - struct counter_device_attr_group *const group, 405 - struct counter_signal *const signal) 406 - { 407 - const size_t num_ext = signal->num_ext; 408 - size_t i; 409 - const struct counter_signal_ext *ext; 410 - struct counter_signal_ext_unit *signal_ext_comp; 411 - struct counter_attr_parm parm; 412 - int err; 413 - 414 - /* Create an attribute for each extension */ 415 - for (i = 0 ; i < num_ext; i++) { 416 - ext = signal->ext + i; 417 - 418 - /* Allocate signal_ext attribute component */ 419 - signal_ext_comp = kmalloc(sizeof(*signal_ext_comp), GFP_KERNEL); 420 - if (!signal_ext_comp) { 421 - err = -ENOMEM; 422 - goto err_free_attr_list; 423 - } 424 - signal_ext_comp->signal = signal; 425 - signal_ext_comp->ext = ext; 426 - 427 - /* Allocate a Counter device attribute */ 428 - parm.group = group; 429 - parm.prefix = ""; 430 - parm.name = ext->name; 431 - parm.show = (ext->read) ? counter_signal_ext_show : NULL; 432 - parm.store = (ext->write) ? counter_signal_ext_store : NULL; 433 - parm.component = signal_ext_comp; 434 - err = counter_attribute_create(&parm); 435 - if (err) { 436 - kfree(signal_ext_comp); 437 - goto err_free_attr_list; 438 - } 439 - } 440 - 441 - return 0; 442 - 443 - err_free_attr_list: 444 - counter_device_attr_list_free(&group->attr_list); 445 - return err; 446 - } 447 - 448 - static int counter_signal_attributes_create( 449 - struct counter_device_attr_group *const group, 450 - const struct counter_device *const counter, 451 - struct counter_signal *const signal) 452 - { 453 - struct counter_signal_unit *signal_comp; 454 - struct counter_attr_parm parm; 455 - int err; 456 - 457 - /* Allocate Signal attribute component */ 458 - signal_comp = kmalloc(sizeof(*signal_comp), GFP_KERNEL); 459 - if (!signal_comp) 460 - return -ENOMEM; 461 - signal_comp->signal = signal; 462 - 463 - /* Create main Signal attribute */ 464 - parm.group = group; 465 - parm.prefix = ""; 466 - parm.name = "signal"; 467 - parm.show = (counter->ops->signal_read) ? counter_signal_show : NULL; 468 - parm.store = NULL; 469 - parm.component = signal_comp; 470 - err = counter_attribute_create(&parm); 471 - if (err) { 472 - kfree(signal_comp); 473 - return err; 474 - } 475 - 476 - /* Create Signal name attribute */ 477 - err = counter_name_attribute_create(group, signal->name); 478 - if (err) 479 - goto err_free_attr_list; 480 - 481 - /* Register Signal extension attributes */ 482 - err = counter_signal_ext_register(group, signal); 483 - if (err) 484 - goto err_free_attr_list; 485 - 486 - return 0; 487 - 488 - err_free_attr_list: 489 - counter_device_attr_list_free(&group->attr_list); 490 - return err; 491 - } 492 - 493 - static int counter_signals_register( 494 - struct counter_device_attr_group *const groups_list, 495 - const struct counter_device *const counter) 496 - { 497 - const size_t num_signals = counter->num_signals; 498 - size_t i; 499 - struct counter_signal *signal; 500 - const char *name; 501 - int err; 502 - 503 - /* Register each Signal */ 504 - for (i = 0; i < num_signals; i++) { 505 - signal = counter->signals + i; 506 - 507 - /* Generate Signal attribute directory name */ 508 - name = kasprintf(GFP_KERNEL, "signal%d", signal->id); 509 - if (!name) { 510 - err = -ENOMEM; 511 - goto err_free_attr_groups; 512 - } 513 - groups_list[i].attr_group.name = name; 514 - 515 - /* Create all attributes associated with Signal */ 516 - err = counter_signal_attributes_create(groups_list + i, counter, 517 - signal); 518 - if (err) 519 - goto err_free_attr_groups; 520 - } 521 - 522 - return 0; 523 - 524 - err_free_attr_groups: 525 - do { 526 - kfree(groups_list[i].attr_group.name); 527 - counter_device_attr_list_free(&groups_list[i].attr_list); 528 - } while (i--); 529 - return err; 530 - } 531 - 532 - static const char *const counter_synapse_action_str[] = { 533 - [COUNTER_SYNAPSE_ACTION_NONE] = "none", 534 - [COUNTER_SYNAPSE_ACTION_RISING_EDGE] = "rising edge", 535 - [COUNTER_SYNAPSE_ACTION_FALLING_EDGE] = "falling edge", 536 - [COUNTER_SYNAPSE_ACTION_BOTH_EDGES] = "both edges" 537 - }; 538 - 539 - struct counter_action_unit { 540 - struct counter_synapse *synapse; 541 - struct counter_count *count; 542 - }; 543 - 544 - static ssize_t counter_action_show(struct device *dev, 545 - struct device_attribute *attr, char *buf) 546 - { 547 - const struct counter_device_attr *const devattr = to_counter_attr(attr); 548 - int err; 549 - struct counter_device *const counter = dev_get_drvdata(dev); 550 - const struct counter_action_unit *const component = devattr->component; 551 - struct counter_count *const count = component->count; 552 - struct counter_synapse *const synapse = component->synapse; 553 - size_t action_index; 554 - enum counter_synapse_action action; 555 - 556 - err = counter->ops->action_get(counter, count, synapse, &action_index); 557 - if (err) 558 - return err; 559 - 560 - synapse->action = action_index; 561 - 562 - action = synapse->actions_list[action_index]; 563 - return sprintf(buf, "%s\n", counter_synapse_action_str[action]); 564 - } 565 - 566 - static ssize_t counter_action_store(struct device *dev, 567 - struct device_attribute *attr, 568 - const char *buf, size_t len) 569 - { 570 - const struct counter_device_attr *const devattr = to_counter_attr(attr); 571 - const struct counter_action_unit *const component = devattr->component; 572 - struct counter_synapse *const synapse = component->synapse; 573 - size_t action_index; 574 - const size_t num_actions = synapse->num_actions; 575 - enum counter_synapse_action action; 576 - int err; 577 - struct counter_device *const counter = dev_get_drvdata(dev); 578 - struct counter_count *const count = component->count; 579 - 580 - /* Find requested action mode */ 581 - for (action_index = 0; action_index < num_actions; action_index++) { 582 - action = synapse->actions_list[action_index]; 583 - if (sysfs_streq(buf, counter_synapse_action_str[action])) 584 - break; 585 - } 586 - /* If requested action mode not found */ 587 - if (action_index >= num_actions) 588 - return -EINVAL; 589 - 590 - err = counter->ops->action_set(counter, count, synapse, action_index); 591 - if (err) 592 - return err; 593 - 594 - synapse->action = action_index; 595 - 596 - return len; 597 - } 598 - 599 - struct counter_action_avail_unit { 600 - const enum counter_synapse_action *actions_list; 601 - size_t num_actions; 602 - }; 603 - 604 - static ssize_t counter_synapse_action_available_show(struct device *dev, 605 - struct device_attribute *attr, char *buf) 606 - { 607 - const struct counter_device_attr *const devattr = to_counter_attr(attr); 608 - const struct counter_action_avail_unit *const component = devattr->component; 609 - size_t i; 610 - enum counter_synapse_action action; 611 - ssize_t len = 0; 612 - 613 - for (i = 0; i < component->num_actions; i++) { 614 - action = component->actions_list[i]; 615 - len += sprintf(buf + len, "%s\n", 616 - counter_synapse_action_str[action]); 617 - } 618 - 619 - return len; 620 - } 621 - 622 - static int counter_synapses_register( 623 - struct counter_device_attr_group *const group, 624 - const struct counter_device *const counter, 625 - struct counter_count *const count, const char *const count_attr_name) 626 - { 627 - size_t i; 628 - struct counter_synapse *synapse; 629 - const char *prefix; 630 - struct counter_action_unit *action_comp; 631 - struct counter_attr_parm parm; 632 - int err; 633 - struct counter_action_avail_unit *avail_comp; 634 - 635 - /* Register each Synapse */ 636 - for (i = 0; i < count->num_synapses; i++) { 637 - synapse = count->synapses + i; 638 - 639 - /* Generate attribute prefix */ 640 - prefix = kasprintf(GFP_KERNEL, "signal%d_", 641 - synapse->signal->id); 642 - if (!prefix) { 643 - err = -ENOMEM; 644 - goto err_free_attr_list; 645 - } 646 - 647 - /* Allocate action attribute component */ 648 - action_comp = kmalloc(sizeof(*action_comp), GFP_KERNEL); 649 - if (!action_comp) { 650 - err = -ENOMEM; 651 - goto err_free_prefix; 652 - } 653 - action_comp->synapse = synapse; 654 - action_comp->count = count; 655 - 656 - /* Create action attribute */ 657 - parm.group = group; 658 - parm.prefix = prefix; 659 - parm.name = "action"; 660 - parm.show = (counter->ops->action_get) ? counter_action_show : NULL; 661 - parm.store = (counter->ops->action_set) ? counter_action_store : NULL; 662 - parm.component = action_comp; 663 - err = counter_attribute_create(&parm); 664 - if (err) { 665 - kfree(action_comp); 666 - goto err_free_prefix; 667 - } 668 - 669 - /* Allocate action available attribute component */ 670 - avail_comp = kmalloc(sizeof(*avail_comp), GFP_KERNEL); 671 - if (!avail_comp) { 672 - err = -ENOMEM; 673 - goto err_free_prefix; 674 - } 675 - avail_comp->actions_list = synapse->actions_list; 676 - avail_comp->num_actions = synapse->num_actions; 677 - 678 - /* Create action_available attribute */ 679 - parm.group = group; 680 - parm.prefix = prefix; 681 - parm.name = "action_available"; 682 - parm.show = counter_synapse_action_available_show; 683 - parm.store = NULL; 684 - parm.component = avail_comp; 685 - err = counter_attribute_create(&parm); 686 - if (err) { 687 - kfree(avail_comp); 688 - goto err_free_prefix; 689 - } 690 - 691 - kfree(prefix); 692 - } 693 - 694 - return 0; 695 - 696 - err_free_prefix: 697 - kfree(prefix); 698 - err_free_attr_list: 699 - counter_device_attr_list_free(&group->attr_list); 700 - return err; 701 - } 702 - 703 - struct counter_count_unit { 704 - struct counter_count *count; 705 - }; 706 - 707 - static ssize_t counter_count_show(struct device *dev, 708 - struct device_attribute *attr, 709 - char *buf) 710 - { 711 - struct counter_device *const counter = dev_get_drvdata(dev); 712 - const struct counter_device_attr *const devattr = to_counter_attr(attr); 713 - const struct counter_count_unit *const component = devattr->component; 714 - struct counter_count *const count = component->count; 715 - int err; 716 - unsigned long val; 717 - 718 - err = counter->ops->count_read(counter, count, &val); 719 - if (err) 720 - return err; 721 - 722 - return sprintf(buf, "%lu\n", val); 723 - } 724 - 725 - static ssize_t counter_count_store(struct device *dev, 726 - struct device_attribute *attr, 727 - const char *buf, size_t len) 728 - { 729 - struct counter_device *const counter = dev_get_drvdata(dev); 730 - const struct counter_device_attr *const devattr = to_counter_attr(attr); 731 - const struct counter_count_unit *const component = devattr->component; 732 - struct counter_count *const count = component->count; 733 - int err; 734 - unsigned long val; 735 - 736 - err = kstrtoul(buf, 0, &val); 737 - if (err) 738 - return err; 739 - 740 - err = counter->ops->count_write(counter, count, val); 741 - if (err) 742 - return err; 743 - 744 - return len; 745 - } 746 - 747 - static const char *const counter_function_str[] = { 748 - [COUNTER_FUNCTION_INCREASE] = "increase", 749 - [COUNTER_FUNCTION_DECREASE] = "decrease", 750 - [COUNTER_FUNCTION_PULSE_DIRECTION] = "pulse-direction", 751 - [COUNTER_FUNCTION_QUADRATURE_X1_A] = "quadrature x1 a", 752 - [COUNTER_FUNCTION_QUADRATURE_X1_B] = "quadrature x1 b", 753 - [COUNTER_FUNCTION_QUADRATURE_X2_A] = "quadrature x2 a", 754 - [COUNTER_FUNCTION_QUADRATURE_X2_B] = "quadrature x2 b", 755 - [COUNTER_FUNCTION_QUADRATURE_X4] = "quadrature x4" 756 - }; 757 - 758 - static ssize_t counter_function_show(struct device *dev, 759 - struct device_attribute *attr, char *buf) 760 - { 761 - int err; 762 - struct counter_device *const counter = dev_get_drvdata(dev); 763 - const struct counter_device_attr *const devattr = to_counter_attr(attr); 764 - const struct counter_count_unit *const component = devattr->component; 765 - struct counter_count *const count = component->count; 766 - size_t func_index; 767 - enum counter_function function; 768 - 769 - err = counter->ops->function_get(counter, count, &func_index); 770 - if (err) 771 - return err; 772 - 773 - count->function = func_index; 774 - 775 - function = count->functions_list[func_index]; 776 - return sprintf(buf, "%s\n", counter_function_str[function]); 777 - } 778 - 779 - static ssize_t counter_function_store(struct device *dev, 780 - struct device_attribute *attr, 781 - const char *buf, size_t len) 782 - { 783 - const struct counter_device_attr *const devattr = to_counter_attr(attr); 784 - const struct counter_count_unit *const component = devattr->component; 785 - struct counter_count *const count = component->count; 786 - const size_t num_functions = count->num_functions; 787 - size_t func_index; 788 - enum counter_function function; 789 - int err; 790 - struct counter_device *const counter = dev_get_drvdata(dev); 791 - 792 - /* Find requested Count function mode */ 793 - for (func_index = 0; func_index < num_functions; func_index++) { 794 - function = count->functions_list[func_index]; 795 - if (sysfs_streq(buf, counter_function_str[function])) 796 - break; 797 - } 798 - /* Return error if requested Count function mode not found */ 799 - if (func_index >= num_functions) 800 - return -EINVAL; 801 - 802 - err = counter->ops->function_set(counter, count, func_index); 803 - if (err) 804 - return err; 805 - 806 - count->function = func_index; 807 - 808 - return len; 809 - } 810 - 811 - struct counter_count_ext_unit { 812 - struct counter_count *count; 813 - const struct counter_count_ext *ext; 814 - }; 815 - 816 - static ssize_t counter_count_ext_show(struct device *dev, 817 - struct device_attribute *attr, char *buf) 818 - { 819 - const struct counter_device_attr *const devattr = to_counter_attr(attr); 820 - const struct counter_count_ext_unit *const comp = devattr->component; 821 - const struct counter_count_ext *const ext = comp->ext; 822 - 823 - return ext->read(dev_get_drvdata(dev), comp->count, ext->priv, buf); 824 - } 825 - 826 - static ssize_t counter_count_ext_store(struct device *dev, 827 - struct device_attribute *attr, 828 - const char *buf, size_t len) 829 - { 830 - const struct counter_device_attr *const devattr = to_counter_attr(attr); 831 - const struct counter_count_ext_unit *const comp = devattr->component; 832 - const struct counter_count_ext *const ext = comp->ext; 833 - 834 - return ext->write(dev_get_drvdata(dev), comp->count, ext->priv, buf, 835 - len); 836 - } 837 - 838 - static int counter_count_ext_register( 839 - struct counter_device_attr_group *const group, 840 - struct counter_count *const count) 841 - { 842 - size_t i; 843 - const struct counter_count_ext *ext; 844 - struct counter_count_ext_unit *count_ext_comp; 845 - struct counter_attr_parm parm; 846 - int err; 847 - 848 - /* Create an attribute for each extension */ 849 - for (i = 0 ; i < count->num_ext; i++) { 850 - ext = count->ext + i; 851 - 852 - /* Allocate count_ext attribute component */ 853 - count_ext_comp = kmalloc(sizeof(*count_ext_comp), GFP_KERNEL); 854 - if (!count_ext_comp) { 855 - err = -ENOMEM; 856 - goto err_free_attr_list; 857 - } 858 - count_ext_comp->count = count; 859 - count_ext_comp->ext = ext; 860 - 861 - /* Allocate count_ext attribute */ 862 - parm.group = group; 863 - parm.prefix = ""; 864 - parm.name = ext->name; 865 - parm.show = (ext->read) ? counter_count_ext_show : NULL; 866 - parm.store = (ext->write) ? counter_count_ext_store : NULL; 867 - parm.component = count_ext_comp; 868 - err = counter_attribute_create(&parm); 869 - if (err) { 870 - kfree(count_ext_comp); 871 - goto err_free_attr_list; 872 - } 873 - } 874 - 875 - return 0; 876 - 877 - err_free_attr_list: 878 - counter_device_attr_list_free(&group->attr_list); 879 - return err; 880 - } 881 - 882 - struct counter_func_avail_unit { 883 - const enum counter_function *functions_list; 884 - size_t num_functions; 885 - }; 886 - 887 - static ssize_t counter_function_available_show(struct device *dev, 888 - struct device_attribute *attr, char *buf) 889 - { 890 - const struct counter_device_attr *const devattr = to_counter_attr(attr); 891 - const struct counter_func_avail_unit *const component = devattr->component; 892 - const enum counter_function *const func_list = component->functions_list; 893 - const size_t num_functions = component->num_functions; 894 - size_t i; 895 - enum counter_function function; 896 - ssize_t len = 0; 897 - 898 - for (i = 0; i < num_functions; i++) { 899 - function = func_list[i]; 900 - len += sprintf(buf + len, "%s\n", 901 - counter_function_str[function]); 902 - } 903 - 904 - return len; 905 - } 906 - 907 - static int counter_count_attributes_create( 908 - struct counter_device_attr_group *const group, 909 - const struct counter_device *const counter, 910 - struct counter_count *const count) 911 - { 912 - struct counter_count_unit *count_comp; 913 - struct counter_attr_parm parm; 914 - int err; 915 - struct counter_count_unit *func_comp; 916 - struct counter_func_avail_unit *avail_comp; 917 - 918 - /* Allocate count attribute component */ 919 - count_comp = kmalloc(sizeof(*count_comp), GFP_KERNEL); 920 - if (!count_comp) 921 - return -ENOMEM; 922 - count_comp->count = count; 923 - 924 - /* Create main Count attribute */ 925 - parm.group = group; 926 - parm.prefix = ""; 927 - parm.name = "count"; 928 - parm.show = (counter->ops->count_read) ? counter_count_show : NULL; 929 - parm.store = (counter->ops->count_write) ? counter_count_store : NULL; 930 - parm.component = count_comp; 931 - err = counter_attribute_create(&parm); 932 - if (err) { 933 - kfree(count_comp); 934 - return err; 935 - } 936 - 937 - /* Allocate function attribute component */ 938 - func_comp = kmalloc(sizeof(*func_comp), GFP_KERNEL); 939 - if (!func_comp) { 940 - err = -ENOMEM; 941 - goto err_free_attr_list; 942 - } 943 - func_comp->count = count; 944 - 945 - /* Create Count function attribute */ 946 - parm.group = group; 947 - parm.prefix = ""; 948 - parm.name = "function"; 949 - parm.show = (counter->ops->function_get) ? counter_function_show : NULL; 950 - parm.store = (counter->ops->function_set) ? counter_function_store : NULL; 951 - parm.component = func_comp; 952 - err = counter_attribute_create(&parm); 953 - if (err) { 954 - kfree(func_comp); 955 - goto err_free_attr_list; 956 - } 957 - 958 - /* Allocate function available attribute component */ 959 - avail_comp = kmalloc(sizeof(*avail_comp), GFP_KERNEL); 960 - if (!avail_comp) { 961 - err = -ENOMEM; 962 - goto err_free_attr_list; 963 - } 964 - avail_comp->functions_list = count->functions_list; 965 - avail_comp->num_functions = count->num_functions; 966 - 967 - /* Create Count function_available attribute */ 968 - parm.group = group; 969 - parm.prefix = ""; 970 - parm.name = "function_available"; 971 - parm.show = counter_function_available_show; 972 - parm.store = NULL; 973 - parm.component = avail_comp; 974 - err = counter_attribute_create(&parm); 975 - if (err) { 976 - kfree(avail_comp); 977 - goto err_free_attr_list; 978 - } 979 - 980 - /* Create Count name attribute */ 981 - err = counter_name_attribute_create(group, count->name); 982 - if (err) 983 - goto err_free_attr_list; 984 - 985 - /* Register Count extension attributes */ 986 - err = counter_count_ext_register(group, count); 987 - if (err) 988 - goto err_free_attr_list; 989 - 990 - return 0; 991 - 992 - err_free_attr_list: 993 - counter_device_attr_list_free(&group->attr_list); 994 - return err; 995 - } 996 - 997 - static int counter_counts_register( 998 - struct counter_device_attr_group *const groups_list, 999 - const struct counter_device *const counter) 1000 - { 1001 - size_t i; 1002 - struct counter_count *count; 1003 - const char *name; 1004 - int err; 1005 - 1006 - /* Register each Count */ 1007 - for (i = 0; i < counter->num_counts; i++) { 1008 - count = counter->counts + i; 1009 - 1010 - /* Generate Count attribute directory name */ 1011 - name = kasprintf(GFP_KERNEL, "count%d", count->id); 1012 - if (!name) { 1013 - err = -ENOMEM; 1014 - goto err_free_attr_groups; 1015 - } 1016 - groups_list[i].attr_group.name = name; 1017 - 1018 - /* Register the Synapses associated with each Count */ 1019 - err = counter_synapses_register(groups_list + i, counter, count, 1020 - name); 1021 - if (err) 1022 - goto err_free_attr_groups; 1023 - 1024 - /* Create all attributes associated with Count */ 1025 - err = counter_count_attributes_create(groups_list + i, counter, 1026 - count); 1027 - if (err) 1028 - goto err_free_attr_groups; 1029 - } 1030 - 1031 - return 0; 1032 - 1033 - err_free_attr_groups: 1034 - do { 1035 - kfree(groups_list[i].attr_group.name); 1036 - counter_device_attr_list_free(&groups_list[i].attr_list); 1037 - } while (i--); 1038 - return err; 1039 - } 1040 - 1041 - struct counter_size_unit { 1042 - size_t size; 1043 - }; 1044 - 1045 - static ssize_t counter_device_attr_size_show(struct device *dev, 1046 - struct device_attribute *attr, 1047 - char *buf) 1048 - { 1049 - const struct counter_size_unit *const comp = to_counter_attr(attr)->component; 1050 - 1051 - return sprintf(buf, "%zu\n", comp->size); 1052 - } 1053 - 1054 - static int counter_size_attribute_create( 1055 - struct counter_device_attr_group *const group, 1056 - const size_t size, const char *const name) 1057 - { 1058 - struct counter_size_unit *size_comp; 1059 - struct counter_attr_parm parm; 1060 - int err; 1061 - 1062 - /* Allocate size attribute component */ 1063 - size_comp = kmalloc(sizeof(*size_comp), GFP_KERNEL); 1064 - if (!size_comp) 1065 - return -ENOMEM; 1066 - size_comp->size = size; 1067 - 1068 - parm.group = group; 1069 - parm.prefix = ""; 1070 - parm.name = name; 1071 - parm.show = counter_device_attr_size_show; 1072 - parm.store = NULL; 1073 - parm.component = size_comp; 1074 - err = counter_attribute_create(&parm); 1075 - if (err) 1076 - goto err_free_size_comp; 1077 - 1078 - return 0; 1079 - 1080 - err_free_size_comp: 1081 - kfree(size_comp); 1082 - return err; 1083 - } 1084 - 1085 - struct counter_ext_unit { 1086 - const struct counter_device_ext *ext; 1087 - }; 1088 - 1089 - static ssize_t counter_device_ext_show(struct device *dev, 1090 - struct device_attribute *attr, char *buf) 1091 - { 1092 - const struct counter_device_attr *const devattr = to_counter_attr(attr); 1093 - const struct counter_ext_unit *const component = devattr->component; 1094 - const struct counter_device_ext *const ext = component->ext; 1095 - 1096 - return ext->read(dev_get_drvdata(dev), ext->priv, buf); 1097 - } 1098 - 1099 - static ssize_t counter_device_ext_store(struct device *dev, 1100 - struct device_attribute *attr, 1101 - const char *buf, size_t len) 1102 - { 1103 - const struct counter_device_attr *const devattr = to_counter_attr(attr); 1104 - const struct counter_ext_unit *const component = devattr->component; 1105 - const struct counter_device_ext *const ext = component->ext; 1106 - 1107 - return ext->write(dev_get_drvdata(dev), ext->priv, buf, len); 1108 - } 1109 - 1110 - static int counter_device_ext_register( 1111 - struct counter_device_attr_group *const group, 1112 - struct counter_device *const counter) 1113 - { 1114 - size_t i; 1115 - struct counter_ext_unit *ext_comp; 1116 - struct counter_attr_parm parm; 1117 - int err; 1118 - 1119 - /* Create an attribute for each extension */ 1120 - for (i = 0 ; i < counter->num_ext; i++) { 1121 - /* Allocate extension attribute component */ 1122 - ext_comp = kmalloc(sizeof(*ext_comp), GFP_KERNEL); 1123 - if (!ext_comp) { 1124 - err = -ENOMEM; 1125 - goto err_free_attr_list; 1126 - } 1127 - 1128 - ext_comp->ext = counter->ext + i; 1129 - 1130 - /* Allocate extension attribute */ 1131 - parm.group = group; 1132 - parm.prefix = ""; 1133 - parm.name = counter->ext[i].name; 1134 - parm.show = (counter->ext[i].read) ? counter_device_ext_show : NULL; 1135 - parm.store = (counter->ext[i].write) ? counter_device_ext_store : NULL; 1136 - parm.component = ext_comp; 1137 - err = counter_attribute_create(&parm); 1138 - if (err) { 1139 - kfree(ext_comp); 1140 - goto err_free_attr_list; 1141 - } 1142 - } 1143 - 1144 - return 0; 1145 - 1146 - err_free_attr_list: 1147 - counter_device_attr_list_free(&group->attr_list); 1148 - return err; 1149 - } 1150 - 1151 - static int counter_global_attr_register( 1152 - struct counter_device_attr_group *const group, 1153 - struct counter_device *const counter) 1154 - { 1155 - int err; 1156 - 1157 - /* Create name attribute */ 1158 - err = counter_name_attribute_create(group, counter->name); 1159 - if (err) 1160 - return err; 1161 - 1162 - /* Create num_counts attribute */ 1163 - err = counter_size_attribute_create(group, counter->num_counts, 1164 - "num_counts"); 1165 - if (err) 1166 - goto err_free_attr_list; 1167 - 1168 - /* Create num_signals attribute */ 1169 - err = counter_size_attribute_create(group, counter->num_signals, 1170 - "num_signals"); 1171 - if (err) 1172 - goto err_free_attr_list; 1173 - 1174 - /* Register Counter device extension attributes */ 1175 - err = counter_device_ext_register(group, counter); 1176 - if (err) 1177 - goto err_free_attr_list; 1178 - 1179 - return 0; 1180 - 1181 - err_free_attr_list: 1182 - counter_device_attr_list_free(&group->attr_list); 1183 - return err; 1184 - } 1185 - 1186 - static void counter_device_groups_list_free( 1187 - struct counter_device_attr_group *const groups_list, 1188 - const size_t num_groups) 1189 - { 1190 - struct counter_device_attr_group *group; 1191 - size_t i; 1192 - 1193 - /* loop through all attribute groups (signals, counts, global, etc.) */ 1194 - for (i = 0; i < num_groups; i++) { 1195 - group = groups_list + i; 1196 - 1197 - /* free all attribute group and associated attributes memory */ 1198 - kfree(group->attr_group.name); 1199 - kfree(group->attr_group.attrs); 1200 - counter_device_attr_list_free(&group->attr_list); 1201 - } 1202 - 1203 - kfree(groups_list); 1204 - } 1205 - 1206 - static int counter_device_groups_list_prepare( 1207 - struct counter_device *const counter) 1208 - { 1209 - const size_t total_num_groups = 1210 - counter->num_signals + counter->num_counts + 1; 1211 - struct counter_device_attr_group *groups_list; 1212 - size_t i; 1213 - int err; 1214 - size_t num_groups = 0; 1215 - 1216 - /* Allocate space for attribute groups (signals, counts, and ext) */ 1217 - groups_list = kcalloc(total_num_groups, sizeof(*groups_list), 1218 - GFP_KERNEL); 1219 - if (!groups_list) 1220 - return -ENOMEM; 1221 - 1222 - /* Initialize attribute lists */ 1223 - for (i = 0; i < total_num_groups; i++) 1224 - INIT_LIST_HEAD(&groups_list[i].attr_list); 1225 - 1226 - /* Register Signals */ 1227 - err = counter_signals_register(groups_list, counter); 1228 - if (err) 1229 - goto err_free_groups_list; 1230 - num_groups += counter->num_signals; 1231 - 1232 - /* Register Counts and respective Synapses */ 1233 - err = counter_counts_register(groups_list + num_groups, counter); 1234 - if (err) 1235 - goto err_free_groups_list; 1236 - num_groups += counter->num_counts; 1237 - 1238 - /* Register Counter global attributes */ 1239 - err = counter_global_attr_register(groups_list + num_groups, counter); 1240 - if (err) 1241 - goto err_free_groups_list; 1242 - num_groups++; 1243 - 1244 - /* Store groups_list in device_state */ 1245 - counter->device_state->groups_list = groups_list; 1246 - counter->device_state->num_groups = num_groups; 1247 - 1248 - return 0; 1249 - 1250 - err_free_groups_list: 1251 - counter_device_groups_list_free(groups_list, num_groups); 1252 - return err; 1253 - } 1254 - 1255 - static int counter_device_groups_prepare( 1256 - struct counter_device_state *const device_state) 1257 - { 1258 - size_t i, j; 1259 - struct counter_device_attr_group *group; 1260 - int err; 1261 - struct counter_device_attr *p; 1262 - 1263 - /* Allocate attribute groups for association with device */ 1264 - device_state->groups = kcalloc(device_state->num_groups + 1, 1265 - sizeof(*device_state->groups), 1266 - GFP_KERNEL); 1267 - if (!device_state->groups) 1268 - return -ENOMEM; 1269 - 1270 - /* Prepare each group of attributes for association */ 1271 - for (i = 0; i < device_state->num_groups; i++) { 1272 - group = device_state->groups_list + i; 1273 - 1274 - /* Allocate space for attribute pointers in attribute group */ 1275 - group->attr_group.attrs = kcalloc(group->num_attr + 1, 1276 - sizeof(*group->attr_group.attrs), GFP_KERNEL); 1277 - if (!group->attr_group.attrs) { 1278 - err = -ENOMEM; 1279 - goto err_free_groups; 1280 - } 1281 - 1282 - /* Add attribute pointers to attribute group */ 1283 - j = 0; 1284 - list_for_each_entry(p, &group->attr_list, l) 1285 - group->attr_group.attrs[j++] = &p->dev_attr.attr; 1286 - 1287 - /* Group attributes in attribute group */ 1288 - device_state->groups[i] = &group->attr_group; 1289 - } 1290 - /* Associate attributes with device */ 1291 - device_state->dev.groups = device_state->groups; 1292 - 1293 - return 0; 1294 - 1295 - err_free_groups: 1296 - do { 1297 - group = device_state->groups_list + i; 1298 - kfree(group->attr_group.attrs); 1299 - group->attr_group.attrs = NULL; 1300 - } while (i--); 1301 - kfree(device_state->groups); 1302 - return err; 1303 - } 1304 - 1305 - /* Provides a unique ID for each counter device */ 1306 - static DEFINE_IDA(counter_ida); 1307 - 1308 - static void counter_device_release(struct device *dev) 1309 - { 1310 - struct counter_device *const counter = dev_get_drvdata(dev); 1311 - struct counter_device_state *const device_state = counter->device_state; 1312 - 1313 - kfree(device_state->groups); 1314 - counter_device_groups_list_free(device_state->groups_list, 1315 - device_state->num_groups); 1316 - ida_simple_remove(&counter_ida, device_state->id); 1317 - kfree(device_state); 1318 - } 1319 - 1320 - static struct device_type counter_device_type = { 1321 - .name = "counter_device", 1322 - .release = counter_device_release 1323 - }; 1324 - 1325 - static struct bus_type counter_bus_type = { 1326 - .name = "counter" 1327 - }; 1328 - 1329 - /** 1330 - * counter_register - register Counter to the system 1331 - * @counter: pointer to Counter to register 1332 - * 1333 - * This function registers a Counter to the system. A sysfs "counter" directory 1334 - * will be created and populated with sysfs attributes correlating with the 1335 - * Counter Signals, Synapses, and Counts respectively. 1336 - */ 1337 - int counter_register(struct counter_device *const counter) 1338 - { 1339 - struct counter_device_state *device_state; 1340 - int err; 1341 - 1342 - /* Allocate internal state container for Counter device */ 1343 - device_state = kzalloc(sizeof(*device_state), GFP_KERNEL); 1344 - if (!device_state) 1345 - return -ENOMEM; 1346 - counter->device_state = device_state; 1347 - 1348 - /* Acquire unique ID */ 1349 - device_state->id = ida_simple_get(&counter_ida, 0, 0, GFP_KERNEL); 1350 - if (device_state->id < 0) { 1351 - err = device_state->id; 1352 - goto err_free_device_state; 1353 - } 1354 - 1355 - /* Configure device structure for Counter */ 1356 - device_state->dev.type = &counter_device_type; 1357 - device_state->dev.bus = &counter_bus_type; 1358 - if (counter->parent) { 1359 - device_state->dev.parent = counter->parent; 1360 - device_state->dev.of_node = counter->parent->of_node; 1361 - } 1362 - dev_set_name(&device_state->dev, "counter%d", device_state->id); 1363 - device_initialize(&device_state->dev); 1364 - dev_set_drvdata(&device_state->dev, counter); 1365 - 1366 - /* Prepare device attributes */ 1367 - err = counter_device_groups_list_prepare(counter); 1368 - if (err) 1369 - goto err_free_id; 1370 - 1371 - /* Organize device attributes to groups and match to device */ 1372 - err = counter_device_groups_prepare(device_state); 1373 - if (err) 1374 - goto err_free_groups_list; 1375 - 1376 - /* Add device to system */ 1377 - err = device_add(&device_state->dev); 1378 - if (err) 1379 - goto err_free_groups; 1380 - 1381 - return 0; 1382 - 1383 - err_free_groups: 1384 - kfree(device_state->groups); 1385 - err_free_groups_list: 1386 - counter_device_groups_list_free(device_state->groups_list, 1387 - device_state->num_groups); 1388 - err_free_id: 1389 - ida_simple_remove(&counter_ida, device_state->id); 1390 - err_free_device_state: 1391 - kfree(device_state); 1392 - return err; 1393 - } 1394 - EXPORT_SYMBOL_GPL(counter_register); 1395 - 1396 - /** 1397 - * counter_unregister - unregister Counter from the system 1398 - * @counter: pointer to Counter to unregister 1399 - * 1400 - * The Counter is unregistered from the system; all allocated memory is freed. 1401 - */ 1402 - void counter_unregister(struct counter_device *const counter) 1403 - { 1404 - if (counter) 1405 - device_del(&counter->device_state->dev); 1406 - } 1407 - EXPORT_SYMBOL_GPL(counter_unregister); 1408 - 1409 - static void devm_counter_unreg(struct device *dev, void *res) 1410 - { 1411 - counter_unregister(*(struct counter_device **)res); 1412 - } 1413 - 1414 - /** 1415 - * devm_counter_register - Resource-managed counter_register 1416 - * @dev: device to allocate counter_device for 1417 - * @counter: pointer to Counter to register 1418 - * 1419 - * Managed counter_register. The Counter registered with this function is 1420 - * automatically unregistered on driver detach. This function calls 1421 - * counter_register internally. Refer to that function for more information. 1422 - * 1423 - * If an Counter registered with this function needs to be unregistered 1424 - * separately, devm_counter_unregister must be used. 1425 - * 1426 - * RETURNS: 1427 - * 0 on success, negative error number on failure. 1428 - */ 1429 - int devm_counter_register(struct device *dev, 1430 - struct counter_device *const counter) 1431 - { 1432 - struct counter_device **ptr; 1433 - int ret; 1434 - 1435 - ptr = devres_alloc(devm_counter_unreg, sizeof(*ptr), GFP_KERNEL); 1436 - if (!ptr) 1437 - return -ENOMEM; 1438 - 1439 - ret = counter_register(counter); 1440 - if (!ret) { 1441 - *ptr = counter; 1442 - devres_add(dev, ptr); 1443 - } else { 1444 - devres_free(ptr); 1445 - } 1446 - 1447 - return ret; 1448 - } 1449 - EXPORT_SYMBOL_GPL(devm_counter_register); 1450 - 1451 - static int devm_counter_match(struct device *dev, void *res, void *data) 1452 - { 1453 - struct counter_device **r = res; 1454 - 1455 - if (!r || !*r) { 1456 - WARN_ON(!r || !*r); 1457 - return 0; 1458 - } 1459 - 1460 - return *r == data; 1461 - } 1462 - 1463 - /** 1464 - * devm_counter_unregister - Resource-managed counter_unregister 1465 - * @dev: device this counter_device belongs to 1466 - * @counter: pointer to Counter associated with the device 1467 - * 1468 - * Unregister Counter registered with devm_counter_register. 1469 - */ 1470 - void devm_counter_unregister(struct device *dev, 1471 - struct counter_device *const counter) 1472 - { 1473 - int rc; 1474 - 1475 - rc = devres_release(dev, devm_counter_unreg, devm_counter_match, 1476 - counter); 1477 - WARN_ON(rc); 1478 - } 1479 - EXPORT_SYMBOL_GPL(devm_counter_unregister); 1480 - 1481 - static int __init counter_init(void) 1482 - { 1483 - return bus_register(&counter_bus_type); 1484 - } 1485 - 1486 - static void __exit counter_exit(void) 1487 - { 1488 - bus_unregister(&counter_bus_type); 1489 - } 1490 - 1491 - subsys_initcall(counter_init); 1492 - module_exit(counter_exit); 1493 - 1494 - MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); 1495 - MODULE_DESCRIPTION("Generic Counter interface"); 1496 - MODULE_LICENSE("GPL v2");
+23 -37
drivers/counter/ftm-quaddec.c
··· 14 14 #include <linux/mutex.h> 15 15 #include <linux/counter.h> 16 16 #include <linux/bitfield.h> 17 + #include <linux/types.h> 17 18 18 19 #define FTM_FIELD_UPDATE(ftm, offset, mask, val) \ 19 20 ({ \ ··· 116 115 } 117 116 118 117 static int ftm_quaddec_get_prescaler(struct counter_device *counter, 119 - struct counter_count *count, 120 - size_t *cnt_mode) 118 + struct counter_count *count, u32 *cnt_mode) 121 119 { 122 120 struct ftm_quaddec *ftm = counter->priv; 123 121 uint32_t scflags; ··· 129 129 } 130 130 131 131 static int ftm_quaddec_set_prescaler(struct counter_device *counter, 132 - struct counter_count *count, 133 - size_t cnt_mode) 132 + struct counter_count *count, u32 cnt_mode) 134 133 { 135 134 struct ftm_quaddec *ftm = counter->priv; 136 135 ··· 150 151 "1", "2", "4", "8", "16", "32", "64", "128" 151 152 }; 152 153 153 - static struct counter_count_enum_ext ftm_quaddec_prescaler_enum = { 154 - .items = ftm_quaddec_prescaler, 155 - .num_items = ARRAY_SIZE(ftm_quaddec_prescaler), 156 - .get = ftm_quaddec_get_prescaler, 157 - .set = ftm_quaddec_set_prescaler 158 - }; 159 - 160 - enum ftm_quaddec_synapse_action { 161 - FTM_QUADDEC_SYNAPSE_ACTION_BOTH_EDGES, 162 - }; 163 - 164 154 static const enum counter_synapse_action ftm_quaddec_synapse_actions[] = { 165 - [FTM_QUADDEC_SYNAPSE_ACTION_BOTH_EDGES] = 166 155 COUNTER_SYNAPSE_ACTION_BOTH_EDGES 167 156 }; 168 157 169 - enum ftm_quaddec_count_function { 170 - FTM_QUADDEC_COUNT_ENCODER_MODE_1, 171 - }; 172 - 173 158 static const enum counter_function ftm_quaddec_count_functions[] = { 174 - [FTM_QUADDEC_COUNT_ENCODER_MODE_1] = COUNTER_FUNCTION_QUADRATURE_X4 159 + COUNTER_FUNCTION_QUADRATURE_X4 175 160 }; 176 161 177 162 static int ftm_quaddec_count_read(struct counter_device *counter, 178 163 struct counter_count *count, 179 - unsigned long *val) 164 + u64 *val) 180 165 { 181 166 struct ftm_quaddec *const ftm = counter->priv; 182 167 uint32_t cntval; ··· 174 191 175 192 static int ftm_quaddec_count_write(struct counter_device *counter, 176 193 struct counter_count *count, 177 - const unsigned long val) 194 + const u64 val) 178 195 { 179 196 struct ftm_quaddec *const ftm = counter->priv; 180 197 ··· 188 205 return 0; 189 206 } 190 207 191 - static int ftm_quaddec_count_function_get(struct counter_device *counter, 192 - struct counter_count *count, 193 - size_t *function) 208 + static int ftm_quaddec_count_function_read(struct counter_device *counter, 209 + struct counter_count *count, 210 + enum counter_function *function) 194 211 { 195 - *function = FTM_QUADDEC_COUNT_ENCODER_MODE_1; 212 + *function = COUNTER_FUNCTION_QUADRATURE_X4; 196 213 197 214 return 0; 198 215 } 199 216 200 - static int ftm_quaddec_action_get(struct counter_device *counter, 201 - struct counter_count *count, 202 - struct counter_synapse *synapse, 203 - size_t *action) 217 + static int ftm_quaddec_action_read(struct counter_device *counter, 218 + struct counter_count *count, 219 + struct counter_synapse *synapse, 220 + enum counter_synapse_action *action) 204 221 { 205 - *action = FTM_QUADDEC_SYNAPSE_ACTION_BOTH_EDGES; 222 + *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES; 206 223 207 224 return 0; 208 225 } ··· 210 227 static const struct counter_ops ftm_quaddec_cnt_ops = { 211 228 .count_read = ftm_quaddec_count_read, 212 229 .count_write = ftm_quaddec_count_write, 213 - .function_get = ftm_quaddec_count_function_get, 214 - .action_get = ftm_quaddec_action_get, 230 + .function_read = ftm_quaddec_count_function_read, 231 + .action_read = ftm_quaddec_action_read, 215 232 }; 216 233 217 234 static struct counter_signal ftm_quaddec_signals[] = { ··· 238 255 } 239 256 }; 240 257 241 - static const struct counter_count_ext ftm_quaddec_count_ext[] = { 242 - COUNTER_COUNT_ENUM("prescaler", &ftm_quaddec_prescaler_enum), 243 - COUNTER_COUNT_ENUM_AVAILABLE("prescaler", &ftm_quaddec_prescaler_enum), 258 + static DEFINE_COUNTER_ENUM(ftm_quaddec_prescaler_enum, ftm_quaddec_prescaler); 259 + 260 + static struct counter_comp ftm_quaddec_count_ext[] = { 261 + COUNTER_COMP_COUNT_ENUM("prescaler", ftm_quaddec_get_prescaler, 262 + ftm_quaddec_set_prescaler, 263 + ftm_quaddec_prescaler_enum), 244 264 }; 245 265 246 266 static struct counter_count ftm_quaddec_counts = {
+62 -84
drivers/counter/intel-qep.c
··· 62 62 63 63 #define INTEL_QEP_CLK_PERIOD_NS 10 64 64 65 - #define INTEL_QEP_COUNTER_EXT_RW(_name) \ 66 - { \ 67 - .name = #_name, \ 68 - .read = _name##_read, \ 69 - .write = _name##_write, \ 70 - } 71 - 72 65 struct intel_qep { 73 66 struct counter_device counter; 74 67 struct mutex lock; ··· 107 114 } 108 115 109 116 static int intel_qep_count_read(struct counter_device *counter, 110 - struct counter_count *count, 111 - unsigned long *val) 117 + struct counter_count *count, u64 *val) 112 118 { 113 119 struct intel_qep *const qep = counter->priv; 114 120 ··· 122 130 COUNTER_FUNCTION_QUADRATURE_X4, 123 131 }; 124 132 125 - static int intel_qep_function_get(struct counter_device *counter, 126 - struct counter_count *count, 127 - size_t *function) 133 + static int intel_qep_function_read(struct counter_device *counter, 134 + struct counter_count *count, 135 + enum counter_function *function) 128 136 { 129 - *function = 0; 137 + *function = COUNTER_FUNCTION_QUADRATURE_X4; 130 138 131 139 return 0; 132 140 } ··· 135 143 COUNTER_SYNAPSE_ACTION_BOTH_EDGES, 136 144 }; 137 145 138 - static int intel_qep_action_get(struct counter_device *counter, 139 - struct counter_count *count, 140 - struct counter_synapse *synapse, 141 - size_t *action) 146 + static int intel_qep_action_read(struct counter_device *counter, 147 + struct counter_count *count, 148 + struct counter_synapse *synapse, 149 + enum counter_synapse_action *action) 142 150 { 143 - *action = 0; 151 + *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES; 144 152 return 0; 145 153 } 146 154 147 155 static const struct counter_ops intel_qep_counter_ops = { 148 156 .count_read = intel_qep_count_read, 149 - .function_get = intel_qep_function_get, 150 - .action_get = intel_qep_action_get, 157 + .function_read = intel_qep_function_read, 158 + .action_read = intel_qep_action_read, 151 159 }; 152 160 153 161 #define INTEL_QEP_SIGNAL(_id, _name) { \ ··· 173 181 INTEL_QEP_SYNAPSE(2), 174 182 }; 175 183 176 - static ssize_t ceiling_read(struct counter_device *counter, 177 - struct counter_count *count, 178 - void *priv, char *buf) 184 + static int intel_qep_ceiling_read(struct counter_device *counter, 185 + struct counter_count *count, u64 *ceiling) 179 186 { 180 187 struct intel_qep *qep = counter->priv; 181 - u32 reg; 182 188 183 189 pm_runtime_get_sync(qep->dev); 184 - reg = intel_qep_readl(qep, INTEL_QEPMAX); 190 + *ceiling = intel_qep_readl(qep, INTEL_QEPMAX); 185 191 pm_runtime_put(qep->dev); 186 192 187 - return sysfs_emit(buf, "%u\n", reg); 193 + return 0; 188 194 } 189 195 190 - static ssize_t ceiling_write(struct counter_device *counter, 191 - struct counter_count *count, 192 - void *priv, const char *buf, size_t len) 196 + static int intel_qep_ceiling_write(struct counter_device *counter, 197 + struct counter_count *count, u64 max) 193 198 { 194 199 struct intel_qep *qep = counter->priv; 195 - u32 max; 196 - int ret; 200 + int ret = 0; 197 201 198 - ret = kstrtou32(buf, 0, &max); 199 - if (ret < 0) 200 - return ret; 202 + /* Intel QEP ceiling configuration only supports 32-bit values */ 203 + if (max != (u32)max) 204 + return -ERANGE; 201 205 202 206 mutex_lock(&qep->lock); 203 207 if (qep->enabled) { ··· 204 216 pm_runtime_get_sync(qep->dev); 205 217 intel_qep_writel(qep, INTEL_QEPMAX, max); 206 218 pm_runtime_put(qep->dev); 207 - ret = len; 208 219 209 220 out: 210 221 mutex_unlock(&qep->lock); 211 222 return ret; 212 223 } 213 224 214 - static ssize_t enable_read(struct counter_device *counter, 215 - struct counter_count *count, 216 - void *priv, char *buf) 225 + static int intel_qep_enable_read(struct counter_device *counter, 226 + struct counter_count *count, u8 *enable) 217 227 { 218 228 struct intel_qep *qep = counter->priv; 219 229 220 - return sysfs_emit(buf, "%u\n", qep->enabled); 230 + *enable = qep->enabled; 231 + 232 + return 0; 221 233 } 222 234 223 - static ssize_t enable_write(struct counter_device *counter, 224 - struct counter_count *count, 225 - void *priv, const char *buf, size_t len) 235 + static int intel_qep_enable_write(struct counter_device *counter, 236 + struct counter_count *count, u8 val) 226 237 { 227 238 struct intel_qep *qep = counter->priv; 228 239 u32 reg; 229 - bool val, changed; 230 - int ret; 231 - 232 - ret = kstrtobool(buf, &val); 233 - if (ret) 234 - return ret; 240 + bool changed; 235 241 236 242 mutex_lock(&qep->lock); 237 243 changed = val ^ qep->enabled; ··· 249 267 250 268 out: 251 269 mutex_unlock(&qep->lock); 252 - return len; 270 + return 0; 253 271 } 254 272 255 - static ssize_t spike_filter_ns_read(struct counter_device *counter, 256 - struct counter_count *count, 257 - void *priv, char *buf) 273 + static int intel_qep_spike_filter_ns_read(struct counter_device *counter, 274 + struct counter_count *count, 275 + u64 *length) 258 276 { 259 277 struct intel_qep *qep = counter->priv; 260 278 u32 reg; ··· 263 281 reg = intel_qep_readl(qep, INTEL_QEPCON); 264 282 if (!(reg & INTEL_QEPCON_FLT_EN)) { 265 283 pm_runtime_put(qep->dev); 266 - return sysfs_emit(buf, "0\n"); 284 + return 0; 267 285 } 268 286 reg = INTEL_QEPFLT_MAX_COUNT(intel_qep_readl(qep, INTEL_QEPFLT)); 269 287 pm_runtime_put(qep->dev); 270 288 271 - return sysfs_emit(buf, "%u\n", (reg + 2) * INTEL_QEP_CLK_PERIOD_NS); 289 + *length = (reg + 2) * INTEL_QEP_CLK_PERIOD_NS; 290 + 291 + return 0; 272 292 } 273 293 274 - static ssize_t spike_filter_ns_write(struct counter_device *counter, 275 - struct counter_count *count, 276 - void *priv, const char *buf, size_t len) 294 + static int intel_qep_spike_filter_ns_write(struct counter_device *counter, 295 + struct counter_count *count, 296 + u64 length) 277 297 { 278 298 struct intel_qep *qep = counter->priv; 279 - u32 reg, length; 299 + u32 reg; 280 300 bool enable; 281 - int ret; 282 - 283 - ret = kstrtou32(buf, 0, &length); 284 - if (ret < 0) 285 - return ret; 301 + int ret = 0; 286 302 287 303 /* 288 304 * Spike filter length is (MAX_COUNT + 2) clock periods. 289 305 * Disable filter when userspace writes 0, enable for valid 290 306 * nanoseconds values and error out otherwise. 291 307 */ 292 - length /= INTEL_QEP_CLK_PERIOD_NS; 308 + do_div(length, INTEL_QEP_CLK_PERIOD_NS); 293 309 if (length == 0) { 294 310 enable = false; 295 311 length = 0; ··· 316 336 intel_qep_writel(qep, INTEL_QEPFLT, length); 317 337 intel_qep_writel(qep, INTEL_QEPCON, reg); 318 338 pm_runtime_put(qep->dev); 319 - ret = len; 320 339 321 340 out: 322 341 mutex_unlock(&qep->lock); 323 342 return ret; 324 343 } 325 344 326 - static ssize_t preset_enable_read(struct counter_device *counter, 327 - struct counter_count *count, 328 - void *priv, char *buf) 345 + static int intel_qep_preset_enable_read(struct counter_device *counter, 346 + struct counter_count *count, 347 + u8 *preset_enable) 329 348 { 330 349 struct intel_qep *qep = counter->priv; 331 350 u32 reg; ··· 332 353 pm_runtime_get_sync(qep->dev); 333 354 reg = intel_qep_readl(qep, INTEL_QEPCON); 334 355 pm_runtime_put(qep->dev); 335 - return sysfs_emit(buf, "%u\n", !(reg & INTEL_QEPCON_COUNT_RST_MODE)); 356 + 357 + *preset_enable = !(reg & INTEL_QEPCON_COUNT_RST_MODE); 358 + 359 + return 0; 336 360 } 337 361 338 - static ssize_t preset_enable_write(struct counter_device *counter, 339 - struct counter_count *count, 340 - void *priv, const char *buf, size_t len) 362 + static int intel_qep_preset_enable_write(struct counter_device *counter, 363 + struct counter_count *count, u8 val) 341 364 { 342 365 struct intel_qep *qep = counter->priv; 343 366 u32 reg; 344 - bool val; 345 - int ret; 346 - 347 - ret = kstrtobool(buf, &val); 348 - if (ret) 349 - return ret; 367 + int ret = 0; 350 368 351 369 mutex_lock(&qep->lock); 352 370 if (qep->enabled) { ··· 360 384 361 385 intel_qep_writel(qep, INTEL_QEPCON, reg); 362 386 pm_runtime_put(qep->dev); 363 - ret = len; 364 387 365 388 out: 366 389 mutex_unlock(&qep->lock); ··· 367 392 return ret; 368 393 } 369 394 370 - static const struct counter_count_ext intel_qep_count_ext[] = { 371 - INTEL_QEP_COUNTER_EXT_RW(ceiling), 372 - INTEL_QEP_COUNTER_EXT_RW(enable), 373 - INTEL_QEP_COUNTER_EXT_RW(spike_filter_ns), 374 - INTEL_QEP_COUNTER_EXT_RW(preset_enable) 395 + static struct counter_comp intel_qep_count_ext[] = { 396 + COUNTER_COMP_ENABLE(intel_qep_enable_read, intel_qep_enable_write), 397 + COUNTER_COMP_CEILING(intel_qep_ceiling_read, intel_qep_ceiling_write), 398 + COUNTER_COMP_PRESET_ENABLE(intel_qep_preset_enable_read, 399 + intel_qep_preset_enable_write), 400 + COUNTER_COMP_COUNT_U64("spike_filter_ns", 401 + intel_qep_spike_filter_ns_read, 402 + intel_qep_spike_filter_ns_write), 375 403 }; 376 404 377 405 static struct counter_count intel_qep_counter_count[] = {
+26 -36
drivers/counter/interrupt-cnt.c
··· 10 10 #include <linux/mod_devicetable.h> 11 11 #include <linux/module.h> 12 12 #include <linux/platform_device.h> 13 + #include <linux/types.h> 13 14 14 15 #define INTERRUPT_CNT_NAME "interrupt-cnt" 15 16 ··· 34 33 return IRQ_HANDLED; 35 34 } 36 35 37 - static ssize_t interrupt_cnt_enable_read(struct counter_device *counter, 38 - struct counter_count *count, 39 - void *private, char *buf) 36 + static int interrupt_cnt_enable_read(struct counter_device *counter, 37 + struct counter_count *count, u8 *enable) 40 38 { 41 39 struct interrupt_cnt_priv *priv = counter->priv; 42 40 43 - return sysfs_emit(buf, "%d\n", priv->enabled); 41 + *enable = priv->enabled; 42 + 43 + return 0; 44 44 } 45 45 46 - static ssize_t interrupt_cnt_enable_write(struct counter_device *counter, 47 - struct counter_count *count, 48 - void *private, const char *buf, 49 - size_t len) 46 + static int interrupt_cnt_enable_write(struct counter_device *counter, 47 + struct counter_count *count, u8 enable) 50 48 { 51 49 struct interrupt_cnt_priv *priv = counter->priv; 52 - bool enable; 53 - ssize_t ret; 54 - 55 - ret = kstrtobool(buf, &enable); 56 - if (ret) 57 - return ret; 58 50 59 51 if (priv->enabled == enable) 60 - return len; 52 + return 0; 61 53 62 54 if (enable) { 63 55 priv->enabled = true; ··· 60 66 priv->enabled = false; 61 67 } 62 68 63 - return len; 69 + return 0; 64 70 } 65 71 66 - static const struct counter_count_ext interrupt_cnt_ext[] = { 67 - { 68 - .name = "enable", 69 - .read = interrupt_cnt_enable_read, 70 - .write = interrupt_cnt_enable_write, 71 - }, 72 + static struct counter_comp interrupt_cnt_ext[] = { 73 + COUNTER_COMP_ENABLE(interrupt_cnt_enable_read, 74 + interrupt_cnt_enable_write), 72 75 }; 73 76 74 77 static const enum counter_synapse_action interrupt_cnt_synapse_actions[] = { 75 78 COUNTER_SYNAPSE_ACTION_RISING_EDGE, 76 79 }; 77 80 78 - static int interrupt_cnt_action_get(struct counter_device *counter, 79 - struct counter_count *count, 80 - struct counter_synapse *synapse, 81 - size_t *action) 81 + static int interrupt_cnt_action_read(struct counter_device *counter, 82 + struct counter_count *count, 83 + struct counter_synapse *synapse, 84 + enum counter_synapse_action *action) 82 85 { 83 - *action = 0; 86 + *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE; 84 87 85 88 return 0; 86 89 } 87 90 88 91 static int interrupt_cnt_read(struct counter_device *counter, 89 - struct counter_count *count, unsigned long *val) 92 + struct counter_count *count, u64 *val) 90 93 { 91 94 struct interrupt_cnt_priv *priv = counter->priv; 92 95 ··· 93 102 } 94 103 95 104 static int interrupt_cnt_write(struct counter_device *counter, 96 - struct counter_count *count, 97 - const unsigned long val) 105 + struct counter_count *count, const u64 val) 98 106 { 99 107 struct interrupt_cnt_priv *priv = counter->priv; 100 108 ··· 109 119 COUNTER_FUNCTION_INCREASE, 110 120 }; 111 121 112 - static int interrupt_cnt_function_get(struct counter_device *counter, 113 - struct counter_count *count, 114 - size_t *function) 122 + static int interrupt_cnt_function_read(struct counter_device *counter, 123 + struct counter_count *count, 124 + enum counter_function *function) 115 125 { 116 - *function = 0; 126 + *function = COUNTER_FUNCTION_INCREASE; 117 127 118 128 return 0; 119 129 } ··· 138 148 } 139 149 140 150 static const struct counter_ops interrupt_cnt_ops = { 141 - .action_get = interrupt_cnt_action_get, 151 + .action_read = interrupt_cnt_action_read, 142 152 .count_read = interrupt_cnt_read, 143 153 .count_write = interrupt_cnt_write, 144 - .function_get = interrupt_cnt_function_get, 154 + .function_read = interrupt_cnt_function_read, 145 155 .signal_read = interrupt_cnt_signal_read, 146 156 }; 147 157
+40 -53
drivers/counter/microchip-tcb-capture.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 - /** 2 + /* 3 3 * Copyright (C) 2020 Microchip 4 4 * 5 5 * Author: Kamel Bouhara <kamel.bouhara@bootlin.com> ··· 32 32 bool trig_inverted; 33 33 }; 34 34 35 - enum mchp_tc_count_function { 36 - MCHP_TC_FUNCTION_INCREASE, 37 - MCHP_TC_FUNCTION_QUADRATURE, 38 - }; 39 - 40 35 static const enum counter_function mchp_tc_count_functions[] = { 41 - [MCHP_TC_FUNCTION_INCREASE] = COUNTER_FUNCTION_INCREASE, 42 - [MCHP_TC_FUNCTION_QUADRATURE] = COUNTER_FUNCTION_QUADRATURE_X4, 43 - }; 44 - 45 - enum mchp_tc_synapse_action { 46 - MCHP_TC_SYNAPSE_ACTION_NONE = 0, 47 - MCHP_TC_SYNAPSE_ACTION_RISING_EDGE, 48 - MCHP_TC_SYNAPSE_ACTION_FALLING_EDGE, 49 - MCHP_TC_SYNAPSE_ACTION_BOTH_EDGE 36 + COUNTER_FUNCTION_INCREASE, 37 + COUNTER_FUNCTION_QUADRATURE_X4, 50 38 }; 51 39 52 40 static const enum counter_synapse_action mchp_tc_synapse_actions[] = { 53 - [MCHP_TC_SYNAPSE_ACTION_NONE] = COUNTER_SYNAPSE_ACTION_NONE, 54 - [MCHP_TC_SYNAPSE_ACTION_RISING_EDGE] = COUNTER_SYNAPSE_ACTION_RISING_EDGE, 55 - [MCHP_TC_SYNAPSE_ACTION_FALLING_EDGE] = COUNTER_SYNAPSE_ACTION_FALLING_EDGE, 56 - [MCHP_TC_SYNAPSE_ACTION_BOTH_EDGE] = COUNTER_SYNAPSE_ACTION_BOTH_EDGES, 41 + COUNTER_SYNAPSE_ACTION_NONE, 42 + COUNTER_SYNAPSE_ACTION_RISING_EDGE, 43 + COUNTER_SYNAPSE_ACTION_FALLING_EDGE, 44 + COUNTER_SYNAPSE_ACTION_BOTH_EDGES, 57 45 }; 58 46 59 47 static struct counter_signal mchp_tc_count_signals[] = { ··· 68 80 } 69 81 }; 70 82 71 - static int mchp_tc_count_function_get(struct counter_device *counter, 72 - struct counter_count *count, 73 - size_t *function) 83 + static int mchp_tc_count_function_read(struct counter_device *counter, 84 + struct counter_count *count, 85 + enum counter_function *function) 74 86 { 75 87 struct mchp_tc_data *const priv = counter->priv; 76 88 77 89 if (priv->qdec_mode) 78 - *function = MCHP_TC_FUNCTION_QUADRATURE; 90 + *function = COUNTER_FUNCTION_QUADRATURE_X4; 79 91 else 80 - *function = MCHP_TC_FUNCTION_INCREASE; 92 + *function = COUNTER_FUNCTION_INCREASE; 81 93 82 94 return 0; 83 95 } 84 96 85 - static int mchp_tc_count_function_set(struct counter_device *counter, 86 - struct counter_count *count, 87 - size_t function) 97 + static int mchp_tc_count_function_write(struct counter_device *counter, 98 + struct counter_count *count, 99 + enum counter_function function) 88 100 { 89 101 struct mchp_tc_data *const priv = counter->priv; 90 102 u32 bmr, cmr; ··· 96 108 cmr &= ~ATMEL_TC_WAVE; 97 109 98 110 switch (function) { 99 - case MCHP_TC_FUNCTION_INCREASE: 111 + case COUNTER_FUNCTION_INCREASE: 100 112 priv->qdec_mode = 0; 101 113 /* Set highest rate based on whether soc has gclk or not */ 102 114 bmr &= ~(ATMEL_TC_QDEN | ATMEL_TC_POSEN); ··· 108 120 cmr |= ATMEL_TC_CMR_MASK; 109 121 cmr &= ~(ATMEL_TC_ABETRG | ATMEL_TC_XC0); 110 122 break; 111 - case MCHP_TC_FUNCTION_QUADRATURE: 123 + case COUNTER_FUNCTION_QUADRATURE_X4: 112 124 if (!priv->tc_cfg->has_qdec) 113 125 return -EINVAL; 114 126 /* In QDEC mode settings both channels 0 and 1 are required */ ··· 164 176 return 0; 165 177 } 166 178 167 - static int mchp_tc_count_action_get(struct counter_device *counter, 168 - struct counter_count *count, 169 - struct counter_synapse *synapse, 170 - size_t *action) 179 + static int mchp_tc_count_action_read(struct counter_device *counter, 180 + struct counter_count *count, 181 + struct counter_synapse *synapse, 182 + enum counter_synapse_action *action) 171 183 { 172 184 struct mchp_tc_data *const priv = counter->priv; 173 185 u32 cmr; ··· 176 188 177 189 switch (cmr & ATMEL_TC_ETRGEDG) { 178 190 default: 179 - *action = MCHP_TC_SYNAPSE_ACTION_NONE; 191 + *action = COUNTER_SYNAPSE_ACTION_NONE; 180 192 break; 181 193 case ATMEL_TC_ETRGEDG_RISING: 182 - *action = MCHP_TC_SYNAPSE_ACTION_RISING_EDGE; 194 + *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE; 183 195 break; 184 196 case ATMEL_TC_ETRGEDG_FALLING: 185 - *action = MCHP_TC_SYNAPSE_ACTION_FALLING_EDGE; 197 + *action = COUNTER_SYNAPSE_ACTION_FALLING_EDGE; 186 198 break; 187 199 case ATMEL_TC_ETRGEDG_BOTH: 188 - *action = MCHP_TC_SYNAPSE_ACTION_BOTH_EDGE; 200 + *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES; 189 201 break; 190 202 } 191 203 192 204 return 0; 193 205 } 194 206 195 - static int mchp_tc_count_action_set(struct counter_device *counter, 196 - struct counter_count *count, 197 - struct counter_synapse *synapse, 198 - size_t action) 207 + static int mchp_tc_count_action_write(struct counter_device *counter, 208 + struct counter_count *count, 209 + struct counter_synapse *synapse, 210 + enum counter_synapse_action action) 199 211 { 200 212 struct mchp_tc_data *const priv = counter->priv; 201 213 u32 edge = ATMEL_TC_ETRGEDG_NONE; ··· 205 217 return -EINVAL; 206 218 207 219 switch (action) { 208 - case MCHP_TC_SYNAPSE_ACTION_NONE: 220 + case COUNTER_SYNAPSE_ACTION_NONE: 209 221 edge = ATMEL_TC_ETRGEDG_NONE; 210 222 break; 211 - case MCHP_TC_SYNAPSE_ACTION_RISING_EDGE: 223 + case COUNTER_SYNAPSE_ACTION_RISING_EDGE: 212 224 edge = ATMEL_TC_ETRGEDG_RISING; 213 225 break; 214 - case MCHP_TC_SYNAPSE_ACTION_FALLING_EDGE: 226 + case COUNTER_SYNAPSE_ACTION_FALLING_EDGE: 215 227 edge = ATMEL_TC_ETRGEDG_FALLING; 216 228 break; 217 - case MCHP_TC_SYNAPSE_ACTION_BOTH_EDGE: 229 + case COUNTER_SYNAPSE_ACTION_BOTH_EDGES: 218 230 edge = ATMEL_TC_ETRGEDG_BOTH; 219 231 break; 220 232 default: ··· 228 240 } 229 241 230 242 static int mchp_tc_count_read(struct counter_device *counter, 231 - struct counter_count *count, 232 - unsigned long *val) 243 + struct counter_count *count, u64 *val) 233 244 { 234 245 struct mchp_tc_data *const priv = counter->priv; 235 246 u32 cnt; ··· 251 264 }; 252 265 253 266 static const struct counter_ops mchp_tc_ops = { 254 - .signal_read = mchp_tc_count_signal_read, 255 - .count_read = mchp_tc_count_read, 256 - .function_get = mchp_tc_count_function_get, 257 - .function_set = mchp_tc_count_function_set, 258 - .action_get = mchp_tc_count_action_get, 259 - .action_set = mchp_tc_count_action_set 267 + .signal_read = mchp_tc_count_signal_read, 268 + .count_read = mchp_tc_count_read, 269 + .function_read = mchp_tc_count_function_read, 270 + .function_write = mchp_tc_count_function_write, 271 + .action_read = mchp_tc_count_action_read, 272 + .action_write = mchp_tc_count_action_write 260 273 }; 261 274 262 275 static const struct atmel_tcb_config tcb_rm9200_config = {
+100 -112
drivers/counter/stm32-lptimer-cnt.c
··· 17 17 #include <linux/module.h> 18 18 #include <linux/pinctrl/consumer.h> 19 19 #include <linux/platform_device.h> 20 + #include <linux/types.h> 20 21 21 22 struct stm32_lptim_cnt { 22 23 struct counter_device counter; ··· 108 107 return regmap_update_bits(priv->regmap, STM32_LPTIM_CFGR, mask, val); 109 108 } 110 109 111 - /** 112 - * enum stm32_lptim_cnt_function - enumerates LPTimer counter & encoder modes 113 - * @STM32_LPTIM_COUNTER_INCREASE: up count on IN1 rising, falling or both edges 114 - * @STM32_LPTIM_ENCODER_BOTH_EDGE: count on both edges (IN1 & IN2 quadrature) 115 - * 110 + /* 116 111 * In non-quadrature mode, device counts up on active edge. 117 112 * In quadrature mode, encoder counting scenarios are as follows: 118 113 * +---------+----------+--------------------+--------------------+ ··· 126 129 * | edges | Low -> | Up | Down | Down | Up | 127 130 * +---------+----------+----------+---------+----------+---------+ 128 131 */ 129 - enum stm32_lptim_cnt_function { 130 - STM32_LPTIM_COUNTER_INCREASE, 131 - STM32_LPTIM_ENCODER_BOTH_EDGE, 132 - }; 133 - 134 132 static const enum counter_function stm32_lptim_cnt_functions[] = { 135 - [STM32_LPTIM_COUNTER_INCREASE] = COUNTER_FUNCTION_INCREASE, 136 - [STM32_LPTIM_ENCODER_BOTH_EDGE] = COUNTER_FUNCTION_QUADRATURE_X4, 137 - }; 138 - 139 - enum stm32_lptim_synapse_action { 140 - STM32_LPTIM_SYNAPSE_ACTION_RISING_EDGE, 141 - STM32_LPTIM_SYNAPSE_ACTION_FALLING_EDGE, 142 - STM32_LPTIM_SYNAPSE_ACTION_BOTH_EDGES, 143 - STM32_LPTIM_SYNAPSE_ACTION_NONE, 133 + COUNTER_FUNCTION_INCREASE, 134 + COUNTER_FUNCTION_QUADRATURE_X4, 144 135 }; 145 136 146 137 static const enum counter_synapse_action stm32_lptim_cnt_synapse_actions[] = { 147 - /* Index must match with stm32_lptim_cnt_polarity[] (priv->polarity) */ 148 - [STM32_LPTIM_SYNAPSE_ACTION_RISING_EDGE] = COUNTER_SYNAPSE_ACTION_RISING_EDGE, 149 - [STM32_LPTIM_SYNAPSE_ACTION_FALLING_EDGE] = COUNTER_SYNAPSE_ACTION_FALLING_EDGE, 150 - [STM32_LPTIM_SYNAPSE_ACTION_BOTH_EDGES] = COUNTER_SYNAPSE_ACTION_BOTH_EDGES, 151 - [STM32_LPTIM_SYNAPSE_ACTION_NONE] = COUNTER_SYNAPSE_ACTION_NONE, 138 + COUNTER_SYNAPSE_ACTION_RISING_EDGE, 139 + COUNTER_SYNAPSE_ACTION_FALLING_EDGE, 140 + COUNTER_SYNAPSE_ACTION_BOTH_EDGES, 141 + COUNTER_SYNAPSE_ACTION_NONE, 152 142 }; 153 143 154 144 static int stm32_lptim_cnt_read(struct counter_device *counter, 155 - struct counter_count *count, unsigned long *val) 145 + struct counter_count *count, u64 *val) 156 146 { 157 147 struct stm32_lptim_cnt *const priv = counter->priv; 158 148 u32 cnt; ··· 154 170 return 0; 155 171 } 156 172 157 - static int stm32_lptim_cnt_function_get(struct counter_device *counter, 158 - struct counter_count *count, 159 - size_t *function) 173 + static int stm32_lptim_cnt_function_read(struct counter_device *counter, 174 + struct counter_count *count, 175 + enum counter_function *function) 160 176 { 161 177 struct stm32_lptim_cnt *const priv = counter->priv; 162 178 163 179 if (!priv->quadrature_mode) { 164 - *function = STM32_LPTIM_COUNTER_INCREASE; 180 + *function = COUNTER_FUNCTION_INCREASE; 165 181 return 0; 166 182 } 167 183 168 - if (priv->polarity == STM32_LPTIM_SYNAPSE_ACTION_BOTH_EDGES) { 169 - *function = STM32_LPTIM_ENCODER_BOTH_EDGE; 184 + if (priv->polarity == STM32_LPTIM_CKPOL_BOTH_EDGES) { 185 + *function = COUNTER_FUNCTION_QUADRATURE_X4; 170 186 return 0; 171 187 } 172 188 173 189 return -EINVAL; 174 190 } 175 191 176 - static int stm32_lptim_cnt_function_set(struct counter_device *counter, 177 - struct counter_count *count, 178 - size_t function) 192 + static int stm32_lptim_cnt_function_write(struct counter_device *counter, 193 + struct counter_count *count, 194 + enum counter_function function) 179 195 { 180 196 struct stm32_lptim_cnt *const priv = counter->priv; 181 197 ··· 183 199 return -EBUSY; 184 200 185 201 switch (function) { 186 - case STM32_LPTIM_COUNTER_INCREASE: 202 + case COUNTER_FUNCTION_INCREASE: 187 203 priv->quadrature_mode = 0; 188 204 return 0; 189 - case STM32_LPTIM_ENCODER_BOTH_EDGE: 205 + case COUNTER_FUNCTION_QUADRATURE_X4: 190 206 priv->quadrature_mode = 1; 191 - priv->polarity = STM32_LPTIM_SYNAPSE_ACTION_BOTH_EDGES; 207 + priv->polarity = STM32_LPTIM_CKPOL_BOTH_EDGES; 192 208 return 0; 193 209 default: 194 210 /* should never reach this path */ ··· 196 212 } 197 213 } 198 214 199 - static ssize_t stm32_lptim_cnt_enable_read(struct counter_device *counter, 200 - struct counter_count *count, 201 - void *private, char *buf) 215 + static int stm32_lptim_cnt_enable_read(struct counter_device *counter, 216 + struct counter_count *count, 217 + u8 *enable) 202 218 { 203 219 struct stm32_lptim_cnt *const priv = counter->priv; 204 220 int ret; ··· 207 223 if (ret < 0) 208 224 return ret; 209 225 210 - return scnprintf(buf, PAGE_SIZE, "%u\n", ret); 226 + *enable = ret; 227 + 228 + return 0; 211 229 } 212 230 213 - static ssize_t stm32_lptim_cnt_enable_write(struct counter_device *counter, 214 - struct counter_count *count, 215 - void *private, 216 - const char *buf, size_t len) 231 + static int stm32_lptim_cnt_enable_write(struct counter_device *counter, 232 + struct counter_count *count, 233 + u8 enable) 217 234 { 218 235 struct stm32_lptim_cnt *const priv = counter->priv; 219 - bool enable; 220 236 int ret; 221 - 222 - ret = kstrtobool(buf, &enable); 223 - if (ret) 224 - return ret; 225 237 226 238 /* Check nobody uses the timer, or already disabled/enabled */ 227 239 ret = stm32_lptim_is_enabled(priv); ··· 234 254 if (ret) 235 255 return ret; 236 256 237 - return len; 257 + return 0; 238 258 } 239 259 240 - static ssize_t stm32_lptim_cnt_ceiling_read(struct counter_device *counter, 241 - struct counter_count *count, 242 - void *private, char *buf) 260 + static int stm32_lptim_cnt_ceiling_read(struct counter_device *counter, 261 + struct counter_count *count, 262 + u64 *ceiling) 243 263 { 244 264 struct stm32_lptim_cnt *const priv = counter->priv; 245 265 246 - return snprintf(buf, PAGE_SIZE, "%u\n", priv->ceiling); 266 + *ceiling = priv->ceiling; 267 + 268 + return 0; 247 269 } 248 270 249 - static ssize_t stm32_lptim_cnt_ceiling_write(struct counter_device *counter, 250 - struct counter_count *count, 251 - void *private, 252 - const char *buf, size_t len) 271 + static int stm32_lptim_cnt_ceiling_write(struct counter_device *counter, 272 + struct counter_count *count, 273 + u64 ceiling) 253 274 { 254 275 struct stm32_lptim_cnt *const priv = counter->priv; 255 - unsigned int ceiling; 256 - int ret; 257 276 258 277 if (stm32_lptim_is_enabled(priv)) 259 278 return -EBUSY; 260 - 261 - ret = kstrtouint(buf, 0, &ceiling); 262 - if (ret) 263 - return ret; 264 279 265 280 if (ceiling > STM32_LPTIM_MAX_ARR) 266 281 return -ERANGE; 267 282 268 283 priv->ceiling = ceiling; 269 284 270 - return len; 285 + return 0; 271 286 } 272 287 273 - static const struct counter_count_ext stm32_lptim_cnt_ext[] = { 274 - { 275 - .name = "enable", 276 - .read = stm32_lptim_cnt_enable_read, 277 - .write = stm32_lptim_cnt_enable_write 278 - }, 279 - { 280 - .name = "ceiling", 281 - .read = stm32_lptim_cnt_ceiling_read, 282 - .write = stm32_lptim_cnt_ceiling_write 283 - }, 288 + static struct counter_comp stm32_lptim_cnt_ext[] = { 289 + COUNTER_COMP_ENABLE(stm32_lptim_cnt_enable_read, 290 + stm32_lptim_cnt_enable_write), 291 + COUNTER_COMP_CEILING(stm32_lptim_cnt_ceiling_read, 292 + stm32_lptim_cnt_ceiling_write), 284 293 }; 285 294 286 - static int stm32_lptim_cnt_action_get(struct counter_device *counter, 287 - struct counter_count *count, 288 - struct counter_synapse *synapse, 289 - size_t *action) 295 + static int stm32_lptim_cnt_action_read(struct counter_device *counter, 296 + struct counter_count *count, 297 + struct counter_synapse *synapse, 298 + enum counter_synapse_action *action) 290 299 { 291 300 struct stm32_lptim_cnt *const priv = counter->priv; 292 - size_t function; 301 + enum counter_function function; 293 302 int err; 294 303 295 - err = stm32_lptim_cnt_function_get(counter, count, &function); 304 + err = stm32_lptim_cnt_function_read(counter, count, &function); 296 305 if (err) 297 306 return err; 298 307 299 308 switch (function) { 300 - case STM32_LPTIM_COUNTER_INCREASE: 309 + case COUNTER_FUNCTION_INCREASE: 301 310 /* LP Timer acts as up-counter on input 1 */ 302 - if (synapse->signal->id == count->synapses[0].signal->id) 303 - *action = priv->polarity; 304 - else 305 - *action = STM32_LPTIM_SYNAPSE_ACTION_NONE; 306 - return 0; 307 - case STM32_LPTIM_ENCODER_BOTH_EDGE: 308 - *action = priv->polarity; 311 + if (synapse->signal->id != count->synapses[0].signal->id) { 312 + *action = COUNTER_SYNAPSE_ACTION_NONE; 313 + return 0; 314 + } 315 + 316 + switch (priv->polarity) { 317 + case STM32_LPTIM_CKPOL_RISING_EDGE: 318 + *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE; 319 + return 0; 320 + case STM32_LPTIM_CKPOL_FALLING_EDGE: 321 + *action = COUNTER_SYNAPSE_ACTION_FALLING_EDGE; 322 + return 0; 323 + case STM32_LPTIM_CKPOL_BOTH_EDGES: 324 + *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES; 325 + return 0; 326 + default: 327 + /* should never reach this path */ 328 + return -EINVAL; 329 + } 330 + case COUNTER_FUNCTION_QUADRATURE_X4: 331 + *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES; 309 332 return 0; 310 333 default: 311 334 /* should never reach this path */ ··· 316 333 } 317 334 } 318 335 319 - static int stm32_lptim_cnt_action_set(struct counter_device *counter, 320 - struct counter_count *count, 321 - struct counter_synapse *synapse, 322 - size_t action) 336 + static int stm32_lptim_cnt_action_write(struct counter_device *counter, 337 + struct counter_count *count, 338 + struct counter_synapse *synapse, 339 + enum counter_synapse_action action) 323 340 { 324 341 struct stm32_lptim_cnt *const priv = counter->priv; 325 - size_t function; 342 + enum counter_function function; 326 343 int err; 327 344 328 345 if (stm32_lptim_is_enabled(priv)) 329 346 return -EBUSY; 330 347 331 - err = stm32_lptim_cnt_function_get(counter, count, &function); 348 + err = stm32_lptim_cnt_function_read(counter, count, &function); 332 349 if (err) 333 350 return err; 334 351 335 352 /* only set polarity when in counter mode (on input 1) */ 336 - if (function == STM32_LPTIM_COUNTER_INCREASE 337 - && synapse->signal->id == count->synapses[0].signal->id) { 338 - switch (action) { 339 - case STM32_LPTIM_SYNAPSE_ACTION_RISING_EDGE: 340 - case STM32_LPTIM_SYNAPSE_ACTION_FALLING_EDGE: 341 - case STM32_LPTIM_SYNAPSE_ACTION_BOTH_EDGES: 342 - priv->polarity = action; 343 - return 0; 344 - } 345 - } 353 + if (function != COUNTER_FUNCTION_INCREASE 354 + || synapse->signal->id != count->synapses[0].signal->id) 355 + return -EINVAL; 346 356 347 - return -EINVAL; 357 + switch (action) { 358 + case COUNTER_SYNAPSE_ACTION_RISING_EDGE: 359 + priv->polarity = STM32_LPTIM_CKPOL_RISING_EDGE; 360 + return 0; 361 + case COUNTER_SYNAPSE_ACTION_FALLING_EDGE: 362 + priv->polarity = STM32_LPTIM_CKPOL_FALLING_EDGE; 363 + return 0; 364 + case COUNTER_SYNAPSE_ACTION_BOTH_EDGES: 365 + priv->polarity = STM32_LPTIM_CKPOL_BOTH_EDGES; 366 + return 0; 367 + default: 368 + return -EINVAL; 369 + } 348 370 } 349 371 350 372 static const struct counter_ops stm32_lptim_cnt_ops = { 351 373 .count_read = stm32_lptim_cnt_read, 352 - .function_get = stm32_lptim_cnt_function_get, 353 - .function_set = stm32_lptim_cnt_function_set, 354 - .action_get = stm32_lptim_cnt_action_get, 355 - .action_set = stm32_lptim_cnt_action_set, 374 + .function_read = stm32_lptim_cnt_function_read, 375 + .function_write = stm32_lptim_cnt_function_write, 376 + .action_read = stm32_lptim_cnt_action_read, 377 + .action_write = stm32_lptim_cnt_action_write, 356 378 }; 357 379 358 380 static struct counter_signal stm32_lptim_cnt_signals[] = {
+76 -119
drivers/counter/stm32-timer-cnt.c
··· 13 13 #include <linux/module.h> 14 14 #include <linux/pinctrl/consumer.h> 15 15 #include <linux/platform_device.h> 16 + #include <linux/types.h> 16 17 17 18 #define TIM_CCMR_CCXS (BIT(8) | BIT(0)) 18 19 #define TIM_CCMR_MASK (TIM_CCMR_CC1S | TIM_CCMR_CC2S | \ ··· 37 36 struct stm32_timer_regs bak; 38 37 }; 39 38 40 - /** 41 - * enum stm32_count_function - enumerates stm32 timer counter encoder modes 42 - * @STM32_COUNT_SLAVE_MODE_DISABLED: counts on internal clock when CEN=1 43 - * @STM32_COUNT_ENCODER_MODE_1: counts TI1FP1 edges, depending on TI2FP2 level 44 - * @STM32_COUNT_ENCODER_MODE_2: counts TI2FP2 edges, depending on TI1FP1 level 45 - * @STM32_COUNT_ENCODER_MODE_3: counts on both TI1FP1 and TI2FP2 edges 46 - */ 47 - enum stm32_count_function { 48 - STM32_COUNT_SLAVE_MODE_DISABLED, 49 - STM32_COUNT_ENCODER_MODE_1, 50 - STM32_COUNT_ENCODER_MODE_2, 51 - STM32_COUNT_ENCODER_MODE_3, 52 - }; 53 - 54 39 static const enum counter_function stm32_count_functions[] = { 55 - [STM32_COUNT_SLAVE_MODE_DISABLED] = COUNTER_FUNCTION_INCREASE, 56 - [STM32_COUNT_ENCODER_MODE_1] = COUNTER_FUNCTION_QUADRATURE_X2_A, 57 - [STM32_COUNT_ENCODER_MODE_2] = COUNTER_FUNCTION_QUADRATURE_X2_B, 58 - [STM32_COUNT_ENCODER_MODE_3] = COUNTER_FUNCTION_QUADRATURE_X4, 40 + COUNTER_FUNCTION_INCREASE, 41 + COUNTER_FUNCTION_QUADRATURE_X2_A, 42 + COUNTER_FUNCTION_QUADRATURE_X2_B, 43 + COUNTER_FUNCTION_QUADRATURE_X4, 59 44 }; 60 45 61 46 static int stm32_count_read(struct counter_device *counter, 62 - struct counter_count *count, unsigned long *val) 47 + struct counter_count *count, u64 *val) 63 48 { 64 49 struct stm32_timer_cnt *const priv = counter->priv; 65 50 u32 cnt; ··· 57 70 } 58 71 59 72 static int stm32_count_write(struct counter_device *counter, 60 - struct counter_count *count, 61 - const unsigned long val) 73 + struct counter_count *count, const u64 val) 62 74 { 63 75 struct stm32_timer_cnt *const priv = counter->priv; 64 76 u32 ceiling; ··· 69 83 return regmap_write(priv->regmap, TIM_CNT, val); 70 84 } 71 85 72 - static int stm32_count_function_get(struct counter_device *counter, 73 - struct counter_count *count, 74 - size_t *function) 86 + static int stm32_count_function_read(struct counter_device *counter, 87 + struct counter_count *count, 88 + enum counter_function *function) 75 89 { 76 90 struct stm32_timer_cnt *const priv = counter->priv; 77 91 u32 smcr; ··· 79 93 regmap_read(priv->regmap, TIM_SMCR, &smcr); 80 94 81 95 switch (smcr & TIM_SMCR_SMS) { 82 - case 0: 83 - *function = STM32_COUNT_SLAVE_MODE_DISABLED; 96 + case TIM_SMCR_SMS_SLAVE_MODE_DISABLED: 97 + *function = COUNTER_FUNCTION_INCREASE; 84 98 return 0; 85 - case 1: 86 - *function = STM32_COUNT_ENCODER_MODE_1; 99 + case TIM_SMCR_SMS_ENCODER_MODE_1: 100 + *function = COUNTER_FUNCTION_QUADRATURE_X2_A; 87 101 return 0; 88 - case 2: 89 - *function = STM32_COUNT_ENCODER_MODE_2; 102 + case TIM_SMCR_SMS_ENCODER_MODE_2: 103 + *function = COUNTER_FUNCTION_QUADRATURE_X2_B; 90 104 return 0; 91 - case 3: 92 - *function = STM32_COUNT_ENCODER_MODE_3; 105 + case TIM_SMCR_SMS_ENCODER_MODE_3: 106 + *function = COUNTER_FUNCTION_QUADRATURE_X4; 93 107 return 0; 94 108 default: 95 109 return -EINVAL; 96 110 } 97 111 } 98 112 99 - static int stm32_count_function_set(struct counter_device *counter, 100 - struct counter_count *count, 101 - size_t function) 113 + static int stm32_count_function_write(struct counter_device *counter, 114 + struct counter_count *count, 115 + enum counter_function function) 102 116 { 103 117 struct stm32_timer_cnt *const priv = counter->priv; 104 118 u32 cr1, sms; 105 119 106 120 switch (function) { 107 - case STM32_COUNT_SLAVE_MODE_DISABLED: 108 - sms = 0; 121 + case COUNTER_FUNCTION_INCREASE: 122 + sms = TIM_SMCR_SMS_SLAVE_MODE_DISABLED; 109 123 break; 110 - case STM32_COUNT_ENCODER_MODE_1: 111 - sms = 1; 124 + case COUNTER_FUNCTION_QUADRATURE_X2_A: 125 + sms = TIM_SMCR_SMS_ENCODER_MODE_1; 112 126 break; 113 - case STM32_COUNT_ENCODER_MODE_2: 114 - sms = 2; 127 + case COUNTER_FUNCTION_QUADRATURE_X2_B: 128 + sms = TIM_SMCR_SMS_ENCODER_MODE_2; 115 129 break; 116 - case STM32_COUNT_ENCODER_MODE_3: 117 - sms = 3; 130 + case COUNTER_FUNCTION_QUADRATURE_X4: 131 + sms = TIM_SMCR_SMS_ENCODER_MODE_3; 118 132 break; 119 133 default: 120 134 return -EINVAL; ··· 136 150 return 0; 137 151 } 138 152 139 - static ssize_t stm32_count_direction_read(struct counter_device *counter, 153 + static int stm32_count_direction_read(struct counter_device *counter, 140 154 struct counter_count *count, 141 - void *private, char *buf) 155 + enum counter_count_direction *direction) 142 156 { 143 157 struct stm32_timer_cnt *const priv = counter->priv; 144 - const char *direction; 145 158 u32 cr1; 146 159 147 160 regmap_read(priv->regmap, TIM_CR1, &cr1); 148 - direction = (cr1 & TIM_CR1_DIR) ? "backward" : "forward"; 161 + *direction = (cr1 & TIM_CR1_DIR) ? COUNTER_COUNT_DIRECTION_BACKWARD : 162 + COUNTER_COUNT_DIRECTION_FORWARD; 149 163 150 - return scnprintf(buf, PAGE_SIZE, "%s\n", direction); 164 + return 0; 151 165 } 152 166 153 - static ssize_t stm32_count_ceiling_read(struct counter_device *counter, 154 - struct counter_count *count, 155 - void *private, char *buf) 167 + static int stm32_count_ceiling_read(struct counter_device *counter, 168 + struct counter_count *count, u64 *ceiling) 156 169 { 157 170 struct stm32_timer_cnt *const priv = counter->priv; 158 171 u32 arr; 159 172 160 173 regmap_read(priv->regmap, TIM_ARR, &arr); 161 174 162 - return snprintf(buf, PAGE_SIZE, "%u\n", arr); 175 + *ceiling = arr; 176 + 177 + return 0; 163 178 } 164 179 165 - static ssize_t stm32_count_ceiling_write(struct counter_device *counter, 166 - struct counter_count *count, 167 - void *private, 168 - const char *buf, size_t len) 180 + static int stm32_count_ceiling_write(struct counter_device *counter, 181 + struct counter_count *count, u64 ceiling) 169 182 { 170 183 struct stm32_timer_cnt *const priv = counter->priv; 171 - unsigned int ceiling; 172 - int ret; 173 - 174 - ret = kstrtouint(buf, 0, &ceiling); 175 - if (ret) 176 - return ret; 177 184 178 185 if (ceiling > priv->max_arr) 179 186 return -ERANGE; ··· 175 196 regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, 0); 176 197 regmap_write(priv->regmap, TIM_ARR, ceiling); 177 198 178 - return len; 199 + return 0; 179 200 } 180 201 181 - static ssize_t stm32_count_enable_read(struct counter_device *counter, 182 - struct counter_count *count, 183 - void *private, char *buf) 202 + static int stm32_count_enable_read(struct counter_device *counter, 203 + struct counter_count *count, u8 *enable) 184 204 { 185 205 struct stm32_timer_cnt *const priv = counter->priv; 186 206 u32 cr1; 187 207 188 208 regmap_read(priv->regmap, TIM_CR1, &cr1); 189 209 190 - return scnprintf(buf, PAGE_SIZE, "%d\n", (bool)(cr1 & TIM_CR1_CEN)); 210 + *enable = cr1 & TIM_CR1_CEN; 211 + 212 + return 0; 191 213 } 192 214 193 - static ssize_t stm32_count_enable_write(struct counter_device *counter, 194 - struct counter_count *count, 195 - void *private, 196 - const char *buf, size_t len) 215 + static int stm32_count_enable_write(struct counter_device *counter, 216 + struct counter_count *count, u8 enable) 197 217 { 198 218 struct stm32_timer_cnt *const priv = counter->priv; 199 - int err; 200 219 u32 cr1; 201 - bool enable; 202 - 203 - err = kstrtobool(buf, &enable); 204 - if (err) 205 - return err; 206 220 207 221 if (enable) { 208 222 regmap_read(priv->regmap, TIM_CR1, &cr1); ··· 214 242 /* Keep enabled state to properly handle low power states */ 215 243 priv->enabled = enable; 216 244 217 - return len; 245 + return 0; 218 246 } 219 247 220 - static const struct counter_count_ext stm32_count_ext[] = { 221 - { 222 - .name = "direction", 223 - .read = stm32_count_direction_read, 224 - }, 225 - { 226 - .name = "enable", 227 - .read = stm32_count_enable_read, 228 - .write = stm32_count_enable_write 229 - }, 230 - { 231 - .name = "ceiling", 232 - .read = stm32_count_ceiling_read, 233 - .write = stm32_count_ceiling_write 234 - }, 235 - }; 236 - 237 - enum stm32_synapse_action { 238 - STM32_SYNAPSE_ACTION_NONE, 239 - STM32_SYNAPSE_ACTION_BOTH_EDGES 248 + static struct counter_comp stm32_count_ext[] = { 249 + COUNTER_COMP_DIRECTION(stm32_count_direction_read), 250 + COUNTER_COMP_ENABLE(stm32_count_enable_read, stm32_count_enable_write), 251 + COUNTER_COMP_CEILING(stm32_count_ceiling_read, 252 + stm32_count_ceiling_write), 240 253 }; 241 254 242 255 static const enum counter_synapse_action stm32_synapse_actions[] = { 243 - [STM32_SYNAPSE_ACTION_NONE] = COUNTER_SYNAPSE_ACTION_NONE, 244 - [STM32_SYNAPSE_ACTION_BOTH_EDGES] = COUNTER_SYNAPSE_ACTION_BOTH_EDGES 256 + COUNTER_SYNAPSE_ACTION_NONE, 257 + COUNTER_SYNAPSE_ACTION_BOTH_EDGES 245 258 }; 246 259 247 - static int stm32_action_get(struct counter_device *counter, 248 - struct counter_count *count, 249 - struct counter_synapse *synapse, 250 - size_t *action) 260 + static int stm32_action_read(struct counter_device *counter, 261 + struct counter_count *count, 262 + struct counter_synapse *synapse, 263 + enum counter_synapse_action *action) 251 264 { 252 - size_t function; 265 + enum counter_function function; 253 266 int err; 254 267 255 - err = stm32_count_function_get(counter, count, &function); 268 + err = stm32_count_function_read(counter, count, &function); 256 269 if (err) 257 270 return err; 258 271 259 272 switch (function) { 260 - case STM32_COUNT_SLAVE_MODE_DISABLED: 273 + case COUNTER_FUNCTION_INCREASE: 261 274 /* counts on internal clock when CEN=1 */ 262 - *action = STM32_SYNAPSE_ACTION_NONE; 275 + *action = COUNTER_SYNAPSE_ACTION_NONE; 263 276 return 0; 264 - case STM32_COUNT_ENCODER_MODE_1: 277 + case COUNTER_FUNCTION_QUADRATURE_X2_A: 265 278 /* counts up/down on TI1FP1 edge depending on TI2FP2 level */ 266 279 if (synapse->signal->id == count->synapses[0].signal->id) 267 - *action = STM32_SYNAPSE_ACTION_BOTH_EDGES; 280 + *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES; 268 281 else 269 - *action = STM32_SYNAPSE_ACTION_NONE; 282 + *action = COUNTER_SYNAPSE_ACTION_NONE; 270 283 return 0; 271 - case STM32_COUNT_ENCODER_MODE_2: 284 + case COUNTER_FUNCTION_QUADRATURE_X2_B: 272 285 /* counts up/down on TI2FP2 edge depending on TI1FP1 level */ 273 286 if (synapse->signal->id == count->synapses[1].signal->id) 274 - *action = STM32_SYNAPSE_ACTION_BOTH_EDGES; 287 + *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES; 275 288 else 276 - *action = STM32_SYNAPSE_ACTION_NONE; 289 + *action = COUNTER_SYNAPSE_ACTION_NONE; 277 290 return 0; 278 - case STM32_COUNT_ENCODER_MODE_3: 291 + case COUNTER_FUNCTION_QUADRATURE_X4: 279 292 /* counts up/down on both TI1FP1 and TI2FP2 edges */ 280 - *action = STM32_SYNAPSE_ACTION_BOTH_EDGES; 293 + *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES; 281 294 return 0; 282 295 default: 283 296 return -EINVAL; ··· 272 315 static const struct counter_ops stm32_timer_cnt_ops = { 273 316 .count_read = stm32_count_read, 274 317 .count_write = stm32_count_write, 275 - .function_get = stm32_count_function_get, 276 - .function_set = stm32_count_function_set, 277 - .action_get = stm32_action_get, 318 + .function_read = stm32_count_function_read, 319 + .function_write = stm32_count_function_write, 320 + .action_read = stm32_action_read, 278 321 }; 279 322 280 323 static struct counter_signal stm32_signals[] = {
+98 -82
drivers/counter/ti-eqep.c
··· 13 13 #include <linux/platform_device.h> 14 14 #include <linux/pm_runtime.h> 15 15 #include <linux/regmap.h> 16 + #include <linux/types.h> 16 17 17 18 /* 32-bit registers */ 18 19 #define QPOSCNT 0x0 ··· 74 73 }; 75 74 76 75 /* Position Counter Input Modes */ 77 - enum { 76 + enum ti_eqep_count_func { 78 77 TI_EQEP_COUNT_FUNC_QUAD_COUNT, 79 78 TI_EQEP_COUNT_FUNC_DIR_COUNT, 80 79 TI_EQEP_COUNT_FUNC_UP_COUNT, 81 80 TI_EQEP_COUNT_FUNC_DOWN_COUNT, 82 - }; 83 - 84 - enum { 85 - TI_EQEP_SYNAPSE_ACTION_BOTH_EDGES, 86 - TI_EQEP_SYNAPSE_ACTION_RISING_EDGE, 87 - TI_EQEP_SYNAPSE_ACTION_NONE, 88 81 }; 89 82 90 83 struct ti_eqep_cnt { ··· 88 93 }; 89 94 90 95 static int ti_eqep_count_read(struct counter_device *counter, 91 - struct counter_count *count, unsigned long *val) 96 + struct counter_count *count, u64 *val) 92 97 { 93 98 struct ti_eqep_cnt *priv = counter->priv; 94 99 u32 cnt; ··· 100 105 } 101 106 102 107 static int ti_eqep_count_write(struct counter_device *counter, 103 - struct counter_count *count, unsigned long val) 108 + struct counter_count *count, u64 val) 104 109 { 105 110 struct ti_eqep_cnt *priv = counter->priv; 106 111 u32 max; ··· 112 117 return regmap_write(priv->regmap32, QPOSCNT, val); 113 118 } 114 119 115 - static int ti_eqep_function_get(struct counter_device *counter, 116 - struct counter_count *count, size_t *function) 120 + static int ti_eqep_function_read(struct counter_device *counter, 121 + struct counter_count *count, 122 + enum counter_function *function) 117 123 { 118 124 struct ti_eqep_cnt *priv = counter->priv; 119 125 u32 qdecctl; 120 126 121 127 regmap_read(priv->regmap16, QDECCTL, &qdecctl); 122 - *function = (qdecctl & QDECCTL_QSRC) >> QDECCTL_QSRC_SHIFT; 128 + 129 + switch ((qdecctl & QDECCTL_QSRC) >> QDECCTL_QSRC_SHIFT) { 130 + case TI_EQEP_COUNT_FUNC_QUAD_COUNT: 131 + *function = COUNTER_FUNCTION_QUADRATURE_X4; 132 + break; 133 + case TI_EQEP_COUNT_FUNC_DIR_COUNT: 134 + *function = COUNTER_FUNCTION_PULSE_DIRECTION; 135 + break; 136 + case TI_EQEP_COUNT_FUNC_UP_COUNT: 137 + *function = COUNTER_FUNCTION_INCREASE; 138 + break; 139 + case TI_EQEP_COUNT_FUNC_DOWN_COUNT: 140 + *function = COUNTER_FUNCTION_DECREASE; 141 + break; 142 + } 123 143 124 144 return 0; 125 145 } 126 146 127 - static int ti_eqep_function_set(struct counter_device *counter, 128 - struct counter_count *count, size_t function) 147 + static int ti_eqep_function_write(struct counter_device *counter, 148 + struct counter_count *count, 149 + enum counter_function function) 129 150 { 130 151 struct ti_eqep_cnt *priv = counter->priv; 152 + enum ti_eqep_count_func qsrc; 153 + 154 + switch (function) { 155 + case COUNTER_FUNCTION_QUADRATURE_X4: 156 + qsrc = TI_EQEP_COUNT_FUNC_QUAD_COUNT; 157 + break; 158 + case COUNTER_FUNCTION_PULSE_DIRECTION: 159 + qsrc = TI_EQEP_COUNT_FUNC_DIR_COUNT; 160 + break; 161 + case COUNTER_FUNCTION_INCREASE: 162 + qsrc = TI_EQEP_COUNT_FUNC_UP_COUNT; 163 + break; 164 + case COUNTER_FUNCTION_DECREASE: 165 + qsrc = TI_EQEP_COUNT_FUNC_DOWN_COUNT; 166 + break; 167 + default: 168 + /* should never reach this path */ 169 + return -EINVAL; 170 + } 131 171 132 172 return regmap_write_bits(priv->regmap16, QDECCTL, QDECCTL_QSRC, 133 - function << QDECCTL_QSRC_SHIFT); 173 + qsrc << QDECCTL_QSRC_SHIFT); 134 174 } 135 175 136 - static int ti_eqep_action_get(struct counter_device *counter, 137 - struct counter_count *count, 138 - struct counter_synapse *synapse, size_t *action) 176 + static int ti_eqep_action_read(struct counter_device *counter, 177 + struct counter_count *count, 178 + struct counter_synapse *synapse, 179 + enum counter_synapse_action *action) 139 180 { 140 181 struct ti_eqep_cnt *priv = counter->priv; 141 - size_t function; 182 + enum counter_function function; 142 183 u32 qdecctl; 143 184 int err; 144 185 145 - err = ti_eqep_function_get(counter, count, &function); 186 + err = ti_eqep_function_read(counter, count, &function); 146 187 if (err) 147 188 return err; 148 189 149 190 switch (function) { 150 - case TI_EQEP_COUNT_FUNC_QUAD_COUNT: 191 + case COUNTER_FUNCTION_QUADRATURE_X4: 151 192 /* In quadrature mode, the rising and falling edge of both 152 193 * QEPA and QEPB trigger QCLK. 153 194 */ 154 - *action = TI_EQEP_SYNAPSE_ACTION_BOTH_EDGES; 195 + *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES; 155 196 return 0; 156 - case TI_EQEP_COUNT_FUNC_DIR_COUNT: 197 + case COUNTER_FUNCTION_PULSE_DIRECTION: 157 198 /* In direction-count mode only rising edge of QEPA is counted 158 199 * and QEPB gives direction. 159 200 */ 160 201 switch (synapse->signal->id) { 161 202 case TI_EQEP_SIGNAL_QEPA: 162 - *action = TI_EQEP_SYNAPSE_ACTION_RISING_EDGE; 203 + *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE; 163 204 return 0; 164 205 case TI_EQEP_SIGNAL_QEPB: 165 - *action = TI_EQEP_SYNAPSE_ACTION_NONE; 206 + *action = COUNTER_SYNAPSE_ACTION_NONE; 166 207 return 0; 167 208 default: 168 209 /* should never reach this path */ 169 210 return -EINVAL; 170 211 } 171 - case TI_EQEP_COUNT_FUNC_UP_COUNT: 172 - case TI_EQEP_COUNT_FUNC_DOWN_COUNT: 212 + case COUNTER_FUNCTION_INCREASE: 213 + case COUNTER_FUNCTION_DECREASE: 173 214 /* In up/down-count modes only QEPA is counted and QEPB is not 174 215 * used. 175 216 */ ··· 216 185 return err; 217 186 218 187 if (qdecctl & QDECCTL_XCR) 219 - *action = TI_EQEP_SYNAPSE_ACTION_BOTH_EDGES; 188 + *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES; 220 189 else 221 - *action = TI_EQEP_SYNAPSE_ACTION_RISING_EDGE; 190 + *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE; 222 191 return 0; 223 192 case TI_EQEP_SIGNAL_QEPB: 224 - *action = TI_EQEP_SYNAPSE_ACTION_NONE; 193 + *action = COUNTER_SYNAPSE_ACTION_NONE; 225 194 return 0; 226 195 default: 227 196 /* should never reach this path */ ··· 236 205 static const struct counter_ops ti_eqep_counter_ops = { 237 206 .count_read = ti_eqep_count_read, 238 207 .count_write = ti_eqep_count_write, 239 - .function_get = ti_eqep_function_get, 240 - .function_set = ti_eqep_function_set, 241 - .action_get = ti_eqep_action_get, 208 + .function_read = ti_eqep_function_read, 209 + .function_write = ti_eqep_function_write, 210 + .action_read = ti_eqep_action_read, 242 211 }; 243 212 244 - static ssize_t ti_eqep_position_ceiling_read(struct counter_device *counter, 245 - struct counter_count *count, 246 - void *ext_priv, char *buf) 213 + static int ti_eqep_position_ceiling_read(struct counter_device *counter, 214 + struct counter_count *count, 215 + u64 *ceiling) 247 216 { 248 217 struct ti_eqep_cnt *priv = counter->priv; 249 218 u32 qposmax; 250 219 251 220 regmap_read(priv->regmap32, QPOSMAX, &qposmax); 252 221 253 - return sprintf(buf, "%u\n", qposmax); 222 + *ceiling = qposmax; 223 + 224 + return 0; 254 225 } 255 226 256 - static ssize_t ti_eqep_position_ceiling_write(struct counter_device *counter, 257 - struct counter_count *count, 258 - void *ext_priv, const char *buf, 259 - size_t len) 227 + static int ti_eqep_position_ceiling_write(struct counter_device *counter, 228 + struct counter_count *count, 229 + u64 ceiling) 260 230 { 261 231 struct ti_eqep_cnt *priv = counter->priv; 262 - int err; 263 - u32 res; 264 232 265 - err = kstrtouint(buf, 0, &res); 266 - if (err < 0) 267 - return err; 233 + if (ceiling != (u32)ceiling) 234 + return -ERANGE; 268 235 269 - regmap_write(priv->regmap32, QPOSMAX, res); 236 + regmap_write(priv->regmap32, QPOSMAX, ceiling); 270 237 271 - return len; 238 + return 0; 272 239 } 273 240 274 - static ssize_t ti_eqep_position_enable_read(struct counter_device *counter, 275 - struct counter_count *count, 276 - void *ext_priv, char *buf) 241 + static int ti_eqep_position_enable_read(struct counter_device *counter, 242 + struct counter_count *count, u8 *enable) 277 243 { 278 244 struct ti_eqep_cnt *priv = counter->priv; 279 245 u32 qepctl; 280 246 281 247 regmap_read(priv->regmap16, QEPCTL, &qepctl); 282 248 283 - return sprintf(buf, "%u\n", !!(qepctl & QEPCTL_PHEN)); 249 + *enable = !!(qepctl & QEPCTL_PHEN); 250 + 251 + return 0; 284 252 } 285 253 286 - static ssize_t ti_eqep_position_enable_write(struct counter_device *counter, 287 - struct counter_count *count, 288 - void *ext_priv, const char *buf, 289 - size_t len) 254 + static int ti_eqep_position_enable_write(struct counter_device *counter, 255 + struct counter_count *count, u8 enable) 290 256 { 291 257 struct ti_eqep_cnt *priv = counter->priv; 292 - int err; 293 - bool res; 294 258 295 - err = kstrtobool(buf, &res); 296 - if (err < 0) 297 - return err; 259 + regmap_write_bits(priv->regmap16, QEPCTL, QEPCTL_PHEN, enable ? -1 : 0); 298 260 299 - regmap_write_bits(priv->regmap16, QEPCTL, QEPCTL_PHEN, res ? -1 : 0); 300 - 301 - return len; 261 + return 0; 302 262 } 303 263 304 - static struct counter_count_ext ti_eqep_position_ext[] = { 305 - { 306 - .name = "ceiling", 307 - .read = ti_eqep_position_ceiling_read, 308 - .write = ti_eqep_position_ceiling_write, 309 - }, 310 - { 311 - .name = "enable", 312 - .read = ti_eqep_position_enable_read, 313 - .write = ti_eqep_position_enable_write, 314 - }, 264 + static struct counter_comp ti_eqep_position_ext[] = { 265 + COUNTER_COMP_CEILING(ti_eqep_position_ceiling_read, 266 + ti_eqep_position_ceiling_write), 267 + COUNTER_COMP_ENABLE(ti_eqep_position_enable_read, 268 + ti_eqep_position_enable_write), 315 269 }; 316 270 317 271 static struct counter_signal ti_eqep_signals[] = { ··· 311 295 }; 312 296 313 297 static const enum counter_function ti_eqep_position_functions[] = { 314 - [TI_EQEP_COUNT_FUNC_QUAD_COUNT] = COUNTER_FUNCTION_QUADRATURE_X4, 315 - [TI_EQEP_COUNT_FUNC_DIR_COUNT] = COUNTER_FUNCTION_PULSE_DIRECTION, 316 - [TI_EQEP_COUNT_FUNC_UP_COUNT] = COUNTER_FUNCTION_INCREASE, 317 - [TI_EQEP_COUNT_FUNC_DOWN_COUNT] = COUNTER_FUNCTION_DECREASE, 298 + COUNTER_FUNCTION_QUADRATURE_X4, 299 + COUNTER_FUNCTION_PULSE_DIRECTION, 300 + COUNTER_FUNCTION_INCREASE, 301 + COUNTER_FUNCTION_DECREASE, 318 302 }; 319 303 320 304 static const enum counter_synapse_action ti_eqep_position_synapse_actions[] = { 321 - [TI_EQEP_SYNAPSE_ACTION_BOTH_EDGES] = COUNTER_SYNAPSE_ACTION_BOTH_EDGES, 322 - [TI_EQEP_SYNAPSE_ACTION_RISING_EDGE] = COUNTER_SYNAPSE_ACTION_RISING_EDGE, 323 - [TI_EQEP_SYNAPSE_ACTION_NONE] = COUNTER_SYNAPSE_ACTION_NONE, 305 + COUNTER_SYNAPSE_ACTION_BOTH_EDGES, 306 + COUNTER_SYNAPSE_ACTION_RISING_EDGE, 307 + COUNTER_SYNAPSE_ACTION_NONE, 324 308 }; 325 309 326 310 static struct counter_synapse ti_eqep_position_synapses[] = {
+376 -344
include/linux/counter.h
··· 6 6 #ifndef _COUNTER_H_ 7 7 #define _COUNTER_H_ 8 8 9 - #include <linux/counter_enum.h> 9 + #include <linux/cdev.h> 10 10 #include <linux/device.h> 11 + #include <linux/kernel.h> 12 + #include <linux/kfifo.h> 13 + #include <linux/mutex.h> 14 + #include <linux/spinlock_types.h> 11 15 #include <linux/types.h> 12 - 13 - enum counter_count_direction { 14 - COUNTER_COUNT_DIRECTION_FORWARD = 0, 15 - COUNTER_COUNT_DIRECTION_BACKWARD 16 - }; 17 - extern const char *const counter_count_direction_str[2]; 18 - 19 - enum counter_count_mode { 20 - COUNTER_COUNT_MODE_NORMAL = 0, 21 - COUNTER_COUNT_MODE_RANGE_LIMIT, 22 - COUNTER_COUNT_MODE_NON_RECYCLE, 23 - COUNTER_COUNT_MODE_MODULO_N 24 - }; 25 - extern const char *const counter_count_mode_str[4]; 16 + #include <linux/wait.h> 17 + #include <uapi/linux/counter.h> 26 18 27 19 struct counter_device; 20 + struct counter_count; 21 + struct counter_synapse; 28 22 struct counter_signal; 29 23 24 + enum counter_comp_type { 25 + COUNTER_COMP_U8, 26 + COUNTER_COMP_U64, 27 + COUNTER_COMP_BOOL, 28 + COUNTER_COMP_SIGNAL_LEVEL, 29 + COUNTER_COMP_FUNCTION, 30 + COUNTER_COMP_SYNAPSE_ACTION, 31 + COUNTER_COMP_ENUM, 32 + COUNTER_COMP_COUNT_DIRECTION, 33 + COUNTER_COMP_COUNT_MODE, 34 + }; 35 + 30 36 /** 31 - * struct counter_signal_ext - Counter Signal extensions 32 - * @name: attribute name 33 - * @read: read callback for this attribute; may be NULL 34 - * @write: write callback for this attribute; may be NULL 35 - * @priv: data private to the driver 37 + * struct counter_comp - Counter component node 38 + * @type: Counter component data type 39 + * @name: device-specific component name 40 + * @priv: component-relevant data 41 + * @action_read Synapse action mode read callback. The read value of the 42 + * respective Synapse action mode should be passed back via 43 + * the action parameter. 44 + * @device_u8_read Device u8 component read callback. The read value of the 45 + * respective Device u8 component should be passed back via 46 + * the val parameter. 47 + * @count_u8_read Count u8 component read callback. The read value of the 48 + * respective Count u8 component should be passed back via 49 + * the val parameter. 50 + * @signal_u8_read Signal u8 component read callback. The read value of the 51 + * respective Signal u8 component should be passed back via 52 + * the val parameter. 53 + * @device_u32_read Device u32 component read callback. The read value of 54 + * the respective Device u32 component should be passed 55 + * back via the val parameter. 56 + * @count_u32_read Count u32 component read callback. The read value of the 57 + * respective Count u32 component should be passed back via 58 + * the val parameter. 59 + * @signal_u32_read Signal u32 component read callback. The read value of 60 + * the respective Signal u32 component should be passed 61 + * back via the val parameter. 62 + * @device_u64_read Device u64 component read callback. The read value of 63 + * the respective Device u64 component should be passed 64 + * back via the val parameter. 65 + * @count_u64_read Count u64 component read callback. The read value of the 66 + * respective Count u64 component should be passed back via 67 + * the val parameter. 68 + * @signal_u64_read Signal u64 component read callback. The read value of 69 + * the respective Signal u64 component should be passed 70 + * back via the val parameter. 71 + * @action_write Synapse action mode write callback. The write value of 72 + * the respective Synapse action mode is passed via the 73 + * action parameter. 74 + * @device_u8_write Device u8 component write callback. The write value of 75 + * the respective Device u8 component is passed via the val 76 + * parameter. 77 + * @count_u8_write Count u8 component write callback. The write value of 78 + * the respective Count u8 component is passed via the val 79 + * parameter. 80 + * @signal_u8_write Signal u8 component write callback. The write value of 81 + * the respective Signal u8 component is passed via the val 82 + * parameter. 83 + * @device_u32_write Device u32 component write callback. The write value of 84 + * the respective Device u32 component is passed via the 85 + * val parameter. 86 + * @count_u32_write Count u32 component write callback. The write value of 87 + * the respective Count u32 component is passed via the val 88 + * parameter. 89 + * @signal_u32_write Signal u32 component write callback. The write value of 90 + * the respective Signal u32 component is passed via the 91 + * val parameter. 92 + * @device_u64_write Device u64 component write callback. The write value of 93 + * the respective Device u64 component is passed via the 94 + * val parameter. 95 + * @count_u64_write Count u64 component write callback. The write value of 96 + * the respective Count u64 component is passed via the val 97 + * parameter. 98 + * @signal_u64_write Signal u64 component write callback. The write value of 99 + * the respective Signal u64 component is passed via the 100 + * val parameter. 36 101 */ 37 - struct counter_signal_ext { 102 + struct counter_comp { 103 + enum counter_comp_type type; 38 104 const char *name; 39 - ssize_t (*read)(struct counter_device *counter, 40 - struct counter_signal *signal, void *priv, char *buf); 41 - ssize_t (*write)(struct counter_device *counter, 42 - struct counter_signal *signal, void *priv, 43 - const char *buf, size_t len); 44 105 void *priv; 106 + union { 107 + int (*action_read)(struct counter_device *counter, 108 + struct counter_count *count, 109 + struct counter_synapse *synapse, 110 + enum counter_synapse_action *action); 111 + int (*device_u8_read)(struct counter_device *counter, u8 *val); 112 + int (*count_u8_read)(struct counter_device *counter, 113 + struct counter_count *count, u8 *val); 114 + int (*signal_u8_read)(struct counter_device *counter, 115 + struct counter_signal *signal, u8 *val); 116 + int (*device_u32_read)(struct counter_device *counter, 117 + u32 *val); 118 + int (*count_u32_read)(struct counter_device *counter, 119 + struct counter_count *count, u32 *val); 120 + int (*signal_u32_read)(struct counter_device *counter, 121 + struct counter_signal *signal, u32 *val); 122 + int (*device_u64_read)(struct counter_device *counter, 123 + u64 *val); 124 + int (*count_u64_read)(struct counter_device *counter, 125 + struct counter_count *count, u64 *val); 126 + int (*signal_u64_read)(struct counter_device *counter, 127 + struct counter_signal *signal, u64 *val); 128 + }; 129 + union { 130 + int (*action_write)(struct counter_device *counter, 131 + struct counter_count *count, 132 + struct counter_synapse *synapse, 133 + enum counter_synapse_action action); 134 + int (*device_u8_write)(struct counter_device *counter, u8 val); 135 + int (*count_u8_write)(struct counter_device *counter, 136 + struct counter_count *count, u8 val); 137 + int (*signal_u8_write)(struct counter_device *counter, 138 + struct counter_signal *signal, u8 val); 139 + int (*device_u32_write)(struct counter_device *counter, 140 + u32 val); 141 + int (*count_u32_write)(struct counter_device *counter, 142 + struct counter_count *count, u32 val); 143 + int (*signal_u32_write)(struct counter_device *counter, 144 + struct counter_signal *signal, u32 val); 145 + int (*device_u64_write)(struct counter_device *counter, 146 + u64 val); 147 + int (*count_u64_write)(struct counter_device *counter, 148 + struct counter_count *count, u64 val); 149 + int (*signal_u64_write)(struct counter_device *counter, 150 + struct counter_signal *signal, u64 val); 151 + }; 45 152 }; 46 153 47 154 /** 48 155 * struct counter_signal - Counter Signal node 49 - * @id: unique ID used to identify signal 50 - * @name: device-specific Signal name; ideally, this should match the name 51 - * as it appears in the datasheet documentation 52 - * @ext: optional array of Counter Signal extensions 53 - * @num_ext: number of Counter Signal extensions specified in @ext 54 - * @priv: optional private data supplied by driver 156 + * @id: unique ID used to identify the Signal 157 + * @name: device-specific Signal name 158 + * @ext: optional array of Signal extensions 159 + * @num_ext: number of Signal extensions specified in @ext 55 160 */ 56 161 struct counter_signal { 57 162 int id; 58 163 const char *name; 59 164 60 - const struct counter_signal_ext *ext; 165 + struct counter_comp *ext; 61 166 size_t num_ext; 62 - 63 - void *priv; 64 - }; 65 - 66 - /** 67 - * struct counter_signal_enum_ext - Signal enum extension attribute 68 - * @items: Array of strings 69 - * @num_items: Number of items specified in @items 70 - * @set: Set callback function; may be NULL 71 - * @get: Get callback function; may be NULL 72 - * 73 - * The counter_signal_enum_ext structure can be used to implement enum style 74 - * Signal extension attributes. Enum style attributes are those which have a set 75 - * of strings that map to unsigned integer values. The Generic Counter Signal 76 - * enum extension helper code takes care of mapping between value and string, as 77 - * well as generating a "_available" file which contains a list of all available 78 - * items. The get callback is used to query the currently active item; the index 79 - * of the item within the respective items array is returned via the 'item' 80 - * parameter. The set callback is called when the attribute is updated; the 81 - * 'item' parameter contains the index of the newly activated item within the 82 - * respective items array. 83 - */ 84 - struct counter_signal_enum_ext { 85 - const char * const *items; 86 - size_t num_items; 87 - int (*get)(struct counter_device *counter, 88 - struct counter_signal *signal, size_t *item); 89 - int (*set)(struct counter_device *counter, 90 - struct counter_signal *signal, size_t item); 91 - }; 92 - 93 - /** 94 - * COUNTER_SIGNAL_ENUM() - Initialize Signal enum extension 95 - * @_name: Attribute name 96 - * @_e: Pointer to a counter_signal_enum_ext structure 97 - * 98 - * This should usually be used together with COUNTER_SIGNAL_ENUM_AVAILABLE() 99 - */ 100 - #define COUNTER_SIGNAL_ENUM(_name, _e) \ 101 - { \ 102 - .name = (_name), \ 103 - .read = counter_signal_enum_read, \ 104 - .write = counter_signal_enum_write, \ 105 - .priv = (_e) \ 106 - } 107 - 108 - /** 109 - * COUNTER_SIGNAL_ENUM_AVAILABLE() - Initialize Signal enum available extension 110 - * @_name: Attribute name ("_available" will be appended to the name) 111 - * @_e: Pointer to a counter_signal_enum_ext structure 112 - * 113 - * Creates a read only attribute that lists all the available enum items in a 114 - * newline separated list. This should usually be used together with 115 - * COUNTER_SIGNAL_ENUM() 116 - */ 117 - #define COUNTER_SIGNAL_ENUM_AVAILABLE(_name, _e) \ 118 - { \ 119 - .name = (_name "_available"), \ 120 - .read = counter_signal_enum_available_read, \ 121 - .priv = (_e) \ 122 - } 123 - 124 - enum counter_synapse_action { 125 - COUNTER_SYNAPSE_ACTION_NONE = 0, 126 - COUNTER_SYNAPSE_ACTION_RISING_EDGE, 127 - COUNTER_SYNAPSE_ACTION_FALLING_EDGE, 128 - COUNTER_SYNAPSE_ACTION_BOTH_EDGES 129 167 }; 130 168 131 169 /** 132 170 * struct counter_synapse - Counter Synapse node 133 - * @action: index of current action mode 134 171 * @actions_list: array of available action modes 135 172 * @num_actions: number of action modes specified in @actions_list 136 - * @signal: pointer to associated signal 173 + * @signal: pointer to the associated Signal 137 174 */ 138 175 struct counter_synapse { 139 - size_t action; 140 176 const enum counter_synapse_action *actions_list; 141 177 size_t num_actions; 142 178 143 179 struct counter_signal *signal; 144 180 }; 145 181 146 - struct counter_count; 147 - 148 - /** 149 - * struct counter_count_ext - Counter Count extension 150 - * @name: attribute name 151 - * @read: read callback for this attribute; may be NULL 152 - * @write: write callback for this attribute; may be NULL 153 - * @priv: data private to the driver 154 - */ 155 - struct counter_count_ext { 156 - const char *name; 157 - ssize_t (*read)(struct counter_device *counter, 158 - struct counter_count *count, void *priv, char *buf); 159 - ssize_t (*write)(struct counter_device *counter, 160 - struct counter_count *count, void *priv, 161 - const char *buf, size_t len); 162 - void *priv; 163 - }; 164 - 165 - enum counter_function { 166 - COUNTER_FUNCTION_INCREASE = 0, 167 - COUNTER_FUNCTION_DECREASE, 168 - COUNTER_FUNCTION_PULSE_DIRECTION, 169 - COUNTER_FUNCTION_QUADRATURE_X1_A, 170 - COUNTER_FUNCTION_QUADRATURE_X1_B, 171 - COUNTER_FUNCTION_QUADRATURE_X2_A, 172 - COUNTER_FUNCTION_QUADRATURE_X2_B, 173 - COUNTER_FUNCTION_QUADRATURE_X4 174 - }; 175 - 176 182 /** 177 183 * struct counter_count - Counter Count node 178 - * @id: unique ID used to identify Count 179 - * @name: device-specific Count name; ideally, this should match 180 - * the name as it appears in the datasheet documentation 181 - * @function: index of current function mode 182 - * @functions_list: array available function modes 184 + * @id: unique ID used to identify the Count 185 + * @name: device-specific Count name 186 + * @functions_list: array of available function modes 183 187 * @num_functions: number of function modes specified in @functions_list 184 - * @synapses: array of synapses for initialization 185 - * @num_synapses: number of synapses specified in @synapses 186 - * @ext: optional array of Counter Count extensions 187 - * @num_ext: number of Counter Count extensions specified in @ext 188 - * @priv: optional private data supplied by driver 188 + * @synapses: array of Synapses for initialization 189 + * @num_synapses: number of Synapses specified in @synapses 190 + * @ext: optional array of Count extensions 191 + * @num_ext: number of Count extensions specified in @ext 189 192 */ 190 193 struct counter_count { 191 194 int id; 192 195 const char *name; 193 196 194 - size_t function; 195 197 const enum counter_function *functions_list; 196 198 size_t num_functions; 197 199 198 200 struct counter_synapse *synapses; 199 201 size_t num_synapses; 200 202 201 - const struct counter_count_ext *ext; 203 + struct counter_comp *ext; 202 204 size_t num_ext; 203 - 204 - void *priv; 205 205 }; 206 206 207 207 /** 208 - * struct counter_count_enum_ext - Count enum extension attribute 209 - * @items: Array of strings 210 - * @num_items: Number of items specified in @items 211 - * @set: Set callback function; may be NULL 212 - * @get: Get callback function; may be NULL 213 - * 214 - * The counter_count_enum_ext structure can be used to implement enum style 215 - * Count extension attributes. Enum style attributes are those which have a set 216 - * of strings that map to unsigned integer values. The Generic Counter Count 217 - * enum extension helper code takes care of mapping between value and string, as 218 - * well as generating a "_available" file which contains a list of all available 219 - * items. The get callback is used to query the currently active item; the index 220 - * of the item within the respective items array is returned via the 'item' 221 - * parameter. The set callback is called when the attribute is updated; the 222 - * 'item' parameter contains the index of the newly activated item within the 223 - * respective items array. 208 + * struct counter_event_node - Counter Event node 209 + * @l: list of current watching Counter events 210 + * @event: event that triggers 211 + * @channel: event channel 212 + * @comp_list: list of components to watch when event triggers 224 213 */ 225 - struct counter_count_enum_ext { 226 - const char * const *items; 227 - size_t num_items; 228 - int (*get)(struct counter_device *counter, struct counter_count *count, 229 - size_t *item); 230 - int (*set)(struct counter_device *counter, struct counter_count *count, 231 - size_t item); 232 - }; 233 - 234 - /** 235 - * COUNTER_COUNT_ENUM() - Initialize Count enum extension 236 - * @_name: Attribute name 237 - * @_e: Pointer to a counter_count_enum_ext structure 238 - * 239 - * This should usually be used together with COUNTER_COUNT_ENUM_AVAILABLE() 240 - */ 241 - #define COUNTER_COUNT_ENUM(_name, _e) \ 242 - { \ 243 - .name = (_name), \ 244 - .read = counter_count_enum_read, \ 245 - .write = counter_count_enum_write, \ 246 - .priv = (_e) \ 247 - } 248 - 249 - /** 250 - * COUNTER_COUNT_ENUM_AVAILABLE() - Initialize Count enum available extension 251 - * @_name: Attribute name ("_available" will be appended to the name) 252 - * @_e: Pointer to a counter_count_enum_ext structure 253 - * 254 - * Creates a read only attribute that lists all the available enum items in a 255 - * newline separated list. This should usually be used together with 256 - * COUNTER_COUNT_ENUM() 257 - */ 258 - #define COUNTER_COUNT_ENUM_AVAILABLE(_name, _e) \ 259 - { \ 260 - .name = (_name "_available"), \ 261 - .read = counter_count_enum_available_read, \ 262 - .priv = (_e) \ 263 - } 264 - 265 - /** 266 - * struct counter_device_attr_group - internal container for attribute group 267 - * @attr_group: Counter sysfs attributes group 268 - * @attr_list: list to keep track of created Counter sysfs attributes 269 - * @num_attr: number of Counter sysfs attributes 270 - */ 271 - struct counter_device_attr_group { 272 - struct attribute_group attr_group; 273 - struct list_head attr_list; 274 - size_t num_attr; 275 - }; 276 - 277 - /** 278 - * struct counter_device_state - internal state container for a Counter device 279 - * @id: unique ID used to identify the Counter 280 - * @dev: internal device structure 281 - * @groups_list: attribute groups list (for Signals, Counts, and ext) 282 - * @num_groups: number of attribute groups containers 283 - * @groups: Counter sysfs attribute groups (to populate @dev.groups) 284 - */ 285 - struct counter_device_state { 286 - int id; 287 - struct device dev; 288 - struct counter_device_attr_group *groups_list; 289 - size_t num_groups; 290 - const struct attribute_group **groups; 291 - }; 292 - 293 - enum counter_signal_level { 294 - COUNTER_SIGNAL_LEVEL_LOW, 295 - COUNTER_SIGNAL_LEVEL_HIGH, 214 + struct counter_event_node { 215 + struct list_head l; 216 + u8 event; 217 + u8 channel; 218 + struct list_head comp_list; 296 219 }; 297 220 298 221 /** 299 222 * struct counter_ops - Callbacks from driver 300 - * @signal_read: optional read callback for Signal attribute. The read 301 - * level of the respective Signal should be passed back via 302 - * the level parameter. 303 - * @count_read: optional read callback for Count attribute. The read 304 - * value of the respective Count should be passed back via 305 - * the val parameter. 306 - * @count_write: optional write callback for Count attribute. The write 307 - * value for the respective Count is passed in via the val 223 + * @signal_read: optional read callback for Signals. The read level of 224 + * the respective Signal should be passed back via the 225 + * level parameter. 226 + * @count_read: read callback for Counts. The read value of the 227 + * respective Count should be passed back via the value 308 228 * parameter. 309 - * @function_get: function to get the current count function mode. Returns 310 - * 0 on success and negative error code on error. The index 311 - * of the respective Count's returned function mode should 312 - * be passed back via the function parameter. 313 - * @function_set: function to set the count function mode. function is the 314 - * index of the requested function mode from the respective 315 - * Count's functions_list array. 316 - * @action_get: function to get the current action mode. Returns 0 on 317 - * success and negative error code on error. The index of 318 - * the respective Synapse's returned action mode should be 229 + * @count_write: optional write callback for Counts. The write value for 230 + * the respective Count is passed in via the value 231 + * parameter. 232 + * @function_read: read callback the Count function modes. The read 233 + * function mode of the respective Count should be passed 234 + * back via the function parameter. 235 + * @function_write: optional write callback for Count function modes. The 236 + * function mode to write for the respective Count is 237 + * passed in via the function parameter. 238 + * @action_read: optional read callback the Synapse action modes. The 239 + * read action mode of the respective Synapse should be 319 240 * passed back via the action parameter. 320 - * @action_set: function to set the action mode. action is the index of 321 - * the requested action mode from the respective Synapse's 322 - * actions_list array. 241 + * @action_write: optional write callback for Synapse action modes. The 242 + * action mode to write for the respective Synapse is 243 + * passed in via the action parameter. 244 + * @events_configure: optional write callback to configure events. The list of 245 + * struct counter_event_node may be accessed via the 246 + * events_list member of the counter parameter. 247 + * @watch_validate: optional callback to validate a watch. The Counter 248 + * component watch configuration is passed in via the watch 249 + * parameter. A return value of 0 indicates a valid Counter 250 + * component watch configuration. 323 251 */ 324 252 struct counter_ops { 325 253 int (*signal_read)(struct counter_device *counter, 326 254 struct counter_signal *signal, 327 255 enum counter_signal_level *level); 328 256 int (*count_read)(struct counter_device *counter, 329 - struct counter_count *count, unsigned long *val); 257 + struct counter_count *count, u64 *value); 330 258 int (*count_write)(struct counter_device *counter, 331 - struct counter_count *count, unsigned long val); 332 - int (*function_get)(struct counter_device *counter, 333 - struct counter_count *count, size_t *function); 334 - int (*function_set)(struct counter_device *counter, 335 - struct counter_count *count, size_t function); 336 - int (*action_get)(struct counter_device *counter, 337 - struct counter_count *count, 338 - struct counter_synapse *synapse, size_t *action); 339 - int (*action_set)(struct counter_device *counter, 340 - struct counter_count *count, 341 - struct counter_synapse *synapse, size_t action); 259 + struct counter_count *count, u64 value); 260 + int (*function_read)(struct counter_device *counter, 261 + struct counter_count *count, 262 + enum counter_function *function); 263 + int (*function_write)(struct counter_device *counter, 264 + struct counter_count *count, 265 + enum counter_function function); 266 + int (*action_read)(struct counter_device *counter, 267 + struct counter_count *count, 268 + struct counter_synapse *synapse, 269 + enum counter_synapse_action *action); 270 + int (*action_write)(struct counter_device *counter, 271 + struct counter_count *count, 272 + struct counter_synapse *synapse, 273 + enum counter_synapse_action action); 274 + int (*events_configure)(struct counter_device *counter); 275 + int (*watch_validate)(struct counter_device *counter, 276 + const struct counter_watch *watch); 342 277 }; 343 - 344 - /** 345 - * struct counter_device_ext - Counter device extension 346 - * @name: attribute name 347 - * @read: read callback for this attribute; may be NULL 348 - * @write: write callback for this attribute; may be NULL 349 - * @priv: data private to the driver 350 - */ 351 - struct counter_device_ext { 352 - const char *name; 353 - ssize_t (*read)(struct counter_device *counter, void *priv, char *buf); 354 - ssize_t (*write)(struct counter_device *counter, void *priv, 355 - const char *buf, size_t len); 356 - void *priv; 357 - }; 358 - 359 - /** 360 - * struct counter_device_enum_ext - Counter enum extension attribute 361 - * @items: Array of strings 362 - * @num_items: Number of items specified in @items 363 - * @set: Set callback function; may be NULL 364 - * @get: Get callback function; may be NULL 365 - * 366 - * The counter_device_enum_ext structure can be used to implement enum style 367 - * Counter extension attributes. Enum style attributes are those which have a 368 - * set of strings that map to unsigned integer values. The Generic Counter enum 369 - * extension helper code takes care of mapping between value and string, as well 370 - * as generating a "_available" file which contains a list of all available 371 - * items. The get callback is used to query the currently active item; the index 372 - * of the item within the respective items array is returned via the 'item' 373 - * parameter. The set callback is called when the attribute is updated; the 374 - * 'item' parameter contains the index of the newly activated item within the 375 - * respective items array. 376 - */ 377 - struct counter_device_enum_ext { 378 - const char * const *items; 379 - size_t num_items; 380 - int (*get)(struct counter_device *counter, size_t *item); 381 - int (*set)(struct counter_device *counter, size_t item); 382 - }; 383 - 384 - /** 385 - * COUNTER_DEVICE_ENUM() - Initialize Counter enum extension 386 - * @_name: Attribute name 387 - * @_e: Pointer to a counter_device_enum_ext structure 388 - * 389 - * This should usually be used together with COUNTER_DEVICE_ENUM_AVAILABLE() 390 - */ 391 - #define COUNTER_DEVICE_ENUM(_name, _e) \ 392 - { \ 393 - .name = (_name), \ 394 - .read = counter_device_enum_read, \ 395 - .write = counter_device_enum_write, \ 396 - .priv = (_e) \ 397 - } 398 - 399 - /** 400 - * COUNTER_DEVICE_ENUM_AVAILABLE() - Initialize Counter enum available extension 401 - * @_name: Attribute name ("_available" will be appended to the name) 402 - * @_e: Pointer to a counter_device_enum_ext structure 403 - * 404 - * Creates a read only attribute that lists all the available enum items in a 405 - * newline separated list. This should usually be used together with 406 - * COUNTER_DEVICE_ENUM() 407 - */ 408 - #define COUNTER_DEVICE_ENUM_AVAILABLE(_name, _e) \ 409 - { \ 410 - .name = (_name "_available"), \ 411 - .read = counter_device_enum_available_read, \ 412 - .priv = (_e) \ 413 - } 414 278 415 279 /** 416 280 * struct counter_device - Counter data structure 417 - * @name: name of the device as it appears in the datasheet 281 + * @name: name of the device 418 282 * @parent: optional parent device providing the counters 419 - * @device_state: internal device state container 420 283 * @ops: callbacks from driver 421 284 * @signals: array of Signals 422 285 * @num_signals: number of Signals specified in @signals ··· 288 425 * @ext: optional array of Counter device extensions 289 426 * @num_ext: number of Counter device extensions specified in @ext 290 427 * @priv: optional private data supplied by driver 428 + * @dev: internal device structure 429 + * @chrdev: internal character device structure 430 + * @events_list: list of current watching Counter events 431 + * @events_list_lock: lock to protect Counter events list operations 432 + * @next_events_list: list of next watching Counter events 433 + * @n_events_list_lock: lock to protect Counter next events list operations 434 + * @events: queue of detected Counter events 435 + * @events_wait: wait queue to allow blocking reads of Counter events 436 + * @events_lock: lock to protect Counter events queue read operations 437 + * @chrdev_lock: lock to limit chrdev to a single open at a time 438 + * @ops_exist_lock: lock to prevent use during removal 291 439 */ 292 440 struct counter_device { 293 441 const char *name; 294 442 struct device *parent; 295 - struct counter_device_state *device_state; 296 443 297 444 const struct counter_ops *ops; 298 445 ··· 311 438 struct counter_count *counts; 312 439 size_t num_counts; 313 440 314 - const struct counter_device_ext *ext; 441 + struct counter_comp *ext; 315 442 size_t num_ext; 316 443 317 444 void *priv; 445 + 446 + struct device dev; 447 + struct cdev chrdev; 448 + struct list_head events_list; 449 + spinlock_t events_list_lock; 450 + struct list_head next_events_list; 451 + struct mutex n_events_list_lock; 452 + DECLARE_KFIFO_PTR(events, struct counter_event); 453 + wait_queue_head_t events_wait; 454 + struct mutex events_lock; 455 + /* 456 + * chrdev_lock is locked by counter_chrdev_open() and unlocked by 457 + * counter_chrdev_release(), so a mutex is not possible here because 458 + * chrdev_lock will invariably be held when returning to user space 459 + */ 460 + atomic_t chrdev_lock; 461 + struct mutex ops_exist_lock; 318 462 }; 319 463 320 464 int counter_register(struct counter_device *const counter); 321 465 void counter_unregister(struct counter_device *const counter); 322 466 int devm_counter_register(struct device *dev, 323 467 struct counter_device *const counter); 324 - void devm_counter_unregister(struct device *dev, 325 - struct counter_device *const counter); 468 + void counter_push_event(struct counter_device *const counter, const u8 event, 469 + const u8 channel); 470 + 471 + #define COUNTER_COMP_DEVICE_U8(_name, _read, _write) \ 472 + { \ 473 + .type = COUNTER_COMP_U8, \ 474 + .name = (_name), \ 475 + .device_u8_read = (_read), \ 476 + .device_u8_write = (_write), \ 477 + } 478 + #define COUNTER_COMP_COUNT_U8(_name, _read, _write) \ 479 + { \ 480 + .type = COUNTER_COMP_U8, \ 481 + .name = (_name), \ 482 + .count_u8_read = (_read), \ 483 + .count_u8_write = (_write), \ 484 + } 485 + #define COUNTER_COMP_SIGNAL_U8(_name, _read, _write) \ 486 + { \ 487 + .type = COUNTER_COMP_U8, \ 488 + .name = (_name), \ 489 + .signal_u8_read = (_read), \ 490 + .signal_u8_write = (_write), \ 491 + } 492 + 493 + #define COUNTER_COMP_DEVICE_U64(_name, _read, _write) \ 494 + { \ 495 + .type = COUNTER_COMP_U64, \ 496 + .name = (_name), \ 497 + .device_u64_read = (_read), \ 498 + .device_u64_write = (_write), \ 499 + } 500 + #define COUNTER_COMP_COUNT_U64(_name, _read, _write) \ 501 + { \ 502 + .type = COUNTER_COMP_U64, \ 503 + .name = (_name), \ 504 + .count_u64_read = (_read), \ 505 + .count_u64_write = (_write), \ 506 + } 507 + #define COUNTER_COMP_SIGNAL_U64(_name, _read, _write) \ 508 + { \ 509 + .type = COUNTER_COMP_U64, \ 510 + .name = (_name), \ 511 + .signal_u64_read = (_read), \ 512 + .signal_u64_write = (_write), \ 513 + } 514 + 515 + #define COUNTER_COMP_DEVICE_BOOL(_name, _read, _write) \ 516 + { \ 517 + .type = COUNTER_COMP_BOOL, \ 518 + .name = (_name), \ 519 + .device_u8_read = (_read), \ 520 + .device_u8_write = (_write), \ 521 + } 522 + #define COUNTER_COMP_COUNT_BOOL(_name, _read, _write) \ 523 + { \ 524 + .type = COUNTER_COMP_BOOL, \ 525 + .name = (_name), \ 526 + .count_u8_read = (_read), \ 527 + .count_u8_write = (_write), \ 528 + } 529 + #define COUNTER_COMP_SIGNAL_BOOL(_name, _read, _write) \ 530 + { \ 531 + .type = COUNTER_COMP_BOOL, \ 532 + .name = (_name), \ 533 + .signal_u8_read = (_read), \ 534 + .signal_u8_write = (_write), \ 535 + } 536 + 537 + struct counter_available { 538 + union { 539 + const u32 *enums; 540 + const char *const *strs; 541 + }; 542 + size_t num_items; 543 + }; 544 + 545 + #define DEFINE_COUNTER_AVAILABLE(_name, _enums) \ 546 + struct counter_available _name = { \ 547 + .enums = (_enums), \ 548 + .num_items = ARRAY_SIZE(_enums), \ 549 + } 550 + 551 + #define DEFINE_COUNTER_ENUM(_name, _strs) \ 552 + struct counter_available _name = { \ 553 + .strs = (_strs), \ 554 + .num_items = ARRAY_SIZE(_strs), \ 555 + } 556 + 557 + #define COUNTER_COMP_DEVICE_ENUM(_name, _get, _set, _available) \ 558 + { \ 559 + .type = COUNTER_COMP_ENUM, \ 560 + .name = (_name), \ 561 + .device_u32_read = (_get), \ 562 + .device_u32_write = (_set), \ 563 + .priv = &(_available), \ 564 + } 565 + #define COUNTER_COMP_COUNT_ENUM(_name, _get, _set, _available) \ 566 + { \ 567 + .type = COUNTER_COMP_ENUM, \ 568 + .name = (_name), \ 569 + .count_u32_read = (_get), \ 570 + .count_u32_write = (_set), \ 571 + .priv = &(_available), \ 572 + } 573 + #define COUNTER_COMP_SIGNAL_ENUM(_name, _get, _set, _available) \ 574 + { \ 575 + .type = COUNTER_COMP_ENUM, \ 576 + .name = (_name), \ 577 + .signal_u32_read = (_get), \ 578 + .signal_u32_write = (_set), \ 579 + .priv = &(_available), \ 580 + } 581 + 582 + #define COUNTER_COMP_CEILING(_read, _write) \ 583 + COUNTER_COMP_COUNT_U64("ceiling", _read, _write) 584 + 585 + #define COUNTER_COMP_COUNT_MODE(_read, _write, _available) \ 586 + { \ 587 + .type = COUNTER_COMP_COUNT_MODE, \ 588 + .name = "count_mode", \ 589 + .count_u32_read = (_read), \ 590 + .count_u32_write = (_write), \ 591 + .priv = &(_available), \ 592 + } 593 + 594 + #define COUNTER_COMP_DIRECTION(_read) \ 595 + { \ 596 + .type = COUNTER_COMP_COUNT_DIRECTION, \ 597 + .name = "direction", \ 598 + .count_u32_read = (_read), \ 599 + } 600 + 601 + #define COUNTER_COMP_ENABLE(_read, _write) \ 602 + COUNTER_COMP_COUNT_BOOL("enable", _read, _write) 603 + 604 + #define COUNTER_COMP_FLOOR(_read, _write) \ 605 + COUNTER_COMP_COUNT_U64("floor", _read, _write) 606 + 607 + #define COUNTER_COMP_PRESET(_read, _write) \ 608 + COUNTER_COMP_COUNT_U64("preset", _read, _write) 609 + 610 + #define COUNTER_COMP_PRESET_ENABLE(_read, _write) \ 611 + COUNTER_COMP_COUNT_BOOL("preset_enable", _read, _write) 326 612 327 613 #endif /* _COUNTER_H_ */
-45
include/linux/counter_enum.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - /* 3 - * Counter interface enum functions 4 - * Copyright (C) 2018 William Breathitt Gray 5 - */ 6 - #ifndef _COUNTER_ENUM_H_ 7 - #define _COUNTER_ENUM_H_ 8 - 9 - #include <linux/types.h> 10 - 11 - struct counter_device; 12 - struct counter_signal; 13 - struct counter_count; 14 - 15 - ssize_t counter_signal_enum_read(struct counter_device *counter, 16 - struct counter_signal *signal, void *priv, 17 - char *buf); 18 - ssize_t counter_signal_enum_write(struct counter_device *counter, 19 - struct counter_signal *signal, void *priv, 20 - const char *buf, size_t len); 21 - 22 - ssize_t counter_signal_enum_available_read(struct counter_device *counter, 23 - struct counter_signal *signal, 24 - void *priv, char *buf); 25 - 26 - ssize_t counter_count_enum_read(struct counter_device *counter, 27 - struct counter_count *count, void *priv, 28 - char *buf); 29 - ssize_t counter_count_enum_write(struct counter_device *counter, 30 - struct counter_count *count, void *priv, 31 - const char *buf, size_t len); 32 - 33 - ssize_t counter_count_enum_available_read(struct counter_device *counter, 34 - struct counter_count *count, 35 - void *priv, char *buf); 36 - 37 - ssize_t counter_device_enum_read(struct counter_device *counter, void *priv, 38 - char *buf); 39 - ssize_t counter_device_enum_write(struct counter_device *counter, void *priv, 40 - const char *buf, size_t len); 41 - 42 - ssize_t counter_device_enum_available_read(struct counter_device *counter, 43 - void *priv, char *buf); 44 - 45 - #endif /* _COUNTER_ENUM_H_ */
+5
include/linux/mfd/stm32-lptimer.h
··· 45 45 #define STM32_LPTIM_PRESC GENMASK(11, 9) 46 46 #define STM32_LPTIM_CKPOL GENMASK(2, 1) 47 47 48 + /* STM32_LPTIM_CKPOL */ 49 + #define STM32_LPTIM_CKPOL_RISING_EDGE 0 50 + #define STM32_LPTIM_CKPOL_FALLING_EDGE 1 51 + #define STM32_LPTIM_CKPOL_BOTH_EDGES 2 52 + 48 53 /* STM32_LPTIM_ARR */ 49 54 #define STM32_LPTIM_MAX_ARR 0xFFFF 50 55
+4
include/linux/mfd/stm32-timers.h
··· 82 82 #define MAX_TIM_ICPSC 0x3 83 83 #define TIM_CR2_MMS_SHIFT 4 84 84 #define TIM_CR2_MMS2_SHIFT 20 85 + #define TIM_SMCR_SMS_SLAVE_MODE_DISABLED 0 /* counts on internal clock when CEN=1 */ 86 + #define TIM_SMCR_SMS_ENCODER_MODE_1 1 /* counts TI1FP1 edges, depending on TI2FP2 level */ 87 + #define TIM_SMCR_SMS_ENCODER_MODE_2 2 /* counts TI2FP2 edges, depending on TI1FP1 level */ 88 + #define TIM_SMCR_SMS_ENCODER_MODE_3 3 /* counts on both TI1FP1 and TI2FP2 edges */ 85 89 #define TIM_SMCR_TS_SHIFT 4 86 90 #define TIM_BDTR_BKF_MASK 0xF 87 91 #define TIM_BDTR_BKF_SHIFT(x) (16 + (x) * 4)
+154
include/uapi/linux/counter.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ 2 + /* 3 + * Userspace ABI for Counter character devices 4 + * Copyright (C) 2020 William Breathitt Gray 5 + */ 6 + #ifndef _UAPI_COUNTER_H_ 7 + #define _UAPI_COUNTER_H_ 8 + 9 + #include <linux/ioctl.h> 10 + #include <linux/types.h> 11 + 12 + /* Component type definitions */ 13 + enum counter_component_type { 14 + COUNTER_COMPONENT_NONE, 15 + COUNTER_COMPONENT_SIGNAL, 16 + COUNTER_COMPONENT_COUNT, 17 + COUNTER_COMPONENT_FUNCTION, 18 + COUNTER_COMPONENT_SYNAPSE_ACTION, 19 + COUNTER_COMPONENT_EXTENSION, 20 + }; 21 + 22 + /* Component scope definitions */ 23 + enum counter_scope { 24 + COUNTER_SCOPE_DEVICE, 25 + COUNTER_SCOPE_SIGNAL, 26 + COUNTER_SCOPE_COUNT, 27 + }; 28 + 29 + /** 30 + * struct counter_component - Counter component identification 31 + * @type: component type (one of enum counter_component_type) 32 + * @scope: component scope (one of enum counter_scope) 33 + * @parent: parent ID (matching the ID suffix of the respective parent sysfs 34 + * path as described by the ABI documentation file 35 + * Documentation/ABI/testing/sysfs-bus-counter) 36 + * @id: component ID (matching the ID provided by the respective *_component_id 37 + * sysfs attribute of the desired component) 38 + * 39 + * For example, if the Count 2 ceiling extension of Counter device 4 is desired, 40 + * set type equal to COUNTER_COMPONENT_EXTENSION, scope equal to 41 + * COUNTER_COUNT_SCOPE, parent equal to 2, and id equal to the value provided by 42 + * the respective /sys/bus/counter/devices/counter4/count2/ceiling_component_id 43 + * sysfs attribute. 44 + */ 45 + struct counter_component { 46 + __u8 type; 47 + __u8 scope; 48 + __u8 parent; 49 + __u8 id; 50 + }; 51 + 52 + /* Event type definitions */ 53 + enum counter_event_type { 54 + /* Count value increased past ceiling */ 55 + COUNTER_EVENT_OVERFLOW, 56 + /* Count value decreased past floor */ 57 + COUNTER_EVENT_UNDERFLOW, 58 + /* Count value increased past ceiling, or decreased past floor */ 59 + COUNTER_EVENT_OVERFLOW_UNDERFLOW, 60 + /* Count value reached threshold */ 61 + COUNTER_EVENT_THRESHOLD, 62 + /* Index signal detected */ 63 + COUNTER_EVENT_INDEX, 64 + }; 65 + 66 + /** 67 + * struct counter_watch - Counter component watch configuration 68 + * @component: component to watch when event triggers 69 + * @event: event that triggers (one of enum counter_event_type) 70 + * @channel: event channel (typically 0 unless the device supports concurrent 71 + * events of the same type) 72 + */ 73 + struct counter_watch { 74 + struct counter_component component; 75 + __u8 event; 76 + __u8 channel; 77 + }; 78 + 79 + /* 80 + * Queues a Counter watch for the specified event. 81 + * 82 + * The queued watches will not be applied until COUNTER_ENABLE_EVENTS_IOCTL is 83 + * called. 84 + */ 85 + #define COUNTER_ADD_WATCH_IOCTL _IOW(0x3E, 0x00, struct counter_watch) 86 + /* 87 + * Enables monitoring the events specified by the Counter watches that were 88 + * queued by COUNTER_ADD_WATCH_IOCTL. 89 + * 90 + * If events are already enabled, the new set of watches replaces the old one. 91 + * Calling this ioctl also has the effect of clearing the queue of watches added 92 + * by COUNTER_ADD_WATCH_IOCTL. 93 + */ 94 + #define COUNTER_ENABLE_EVENTS_IOCTL _IO(0x3E, 0x01) 95 + /* 96 + * Stops monitoring the previously enabled events. 97 + */ 98 + #define COUNTER_DISABLE_EVENTS_IOCTL _IO(0x3E, 0x02) 99 + 100 + /** 101 + * struct counter_event - Counter event data 102 + * @timestamp: best estimate of time of event occurrence, in nanoseconds 103 + * @value: component value 104 + * @watch: component watch configuration 105 + * @status: return status (system error number) 106 + */ 107 + struct counter_event { 108 + __aligned_u64 timestamp; 109 + __aligned_u64 value; 110 + struct counter_watch watch; 111 + __u8 status; 112 + }; 113 + 114 + /* Count direction values */ 115 + enum counter_count_direction { 116 + COUNTER_COUNT_DIRECTION_FORWARD, 117 + COUNTER_COUNT_DIRECTION_BACKWARD, 118 + }; 119 + 120 + /* Count mode values */ 121 + enum counter_count_mode { 122 + COUNTER_COUNT_MODE_NORMAL, 123 + COUNTER_COUNT_MODE_RANGE_LIMIT, 124 + COUNTER_COUNT_MODE_NON_RECYCLE, 125 + COUNTER_COUNT_MODE_MODULO_N, 126 + }; 127 + 128 + /* Count function values */ 129 + enum counter_function { 130 + COUNTER_FUNCTION_INCREASE, 131 + COUNTER_FUNCTION_DECREASE, 132 + COUNTER_FUNCTION_PULSE_DIRECTION, 133 + COUNTER_FUNCTION_QUADRATURE_X1_A, 134 + COUNTER_FUNCTION_QUADRATURE_X1_B, 135 + COUNTER_FUNCTION_QUADRATURE_X2_A, 136 + COUNTER_FUNCTION_QUADRATURE_X2_B, 137 + COUNTER_FUNCTION_QUADRATURE_X4, 138 + }; 139 + 140 + /* Signal values */ 141 + enum counter_signal_level { 142 + COUNTER_SIGNAL_LEVEL_LOW, 143 + COUNTER_SIGNAL_LEVEL_HIGH, 144 + }; 145 + 146 + /* Action mode values */ 147 + enum counter_synapse_action { 148 + COUNTER_SYNAPSE_ACTION_NONE, 149 + COUNTER_SYNAPSE_ACTION_RISING_EDGE, 150 + COUNTER_SYNAPSE_ACTION_FALLING_EDGE, 151 + COUNTER_SYNAPSE_ACTION_BOTH_EDGES, 152 + }; 153 + 154 + #endif /* _UAPI_COUNTER_H_ */
+7 -6
tools/Makefile
··· 12 12 @echo ' acpi - ACPI tools' 13 13 @echo ' bpf - misc BPF tools' 14 14 @echo ' cgroup - cgroup tools' 15 + @echo ' counter - counter tools' 15 16 @echo ' cpupower - a tool for all things x86 CPU power' 16 17 @echo ' debugging - tools for debugging' 17 18 @echo ' firewire - the userspace part of nosy, an IEEE-1394 traffic sniffer' ··· 66 65 cpupower: FORCE 67 66 $(call descend,power/$@) 68 67 69 - cgroup firewire hv guest bootconfig spi usb virtio vm bpf iio gpio objtool leds wmi pci firmware debugging tracing: FORCE 68 + cgroup counter firewire hv guest bootconfig spi usb virtio vm bpf iio gpio objtool leds wmi pci firmware debugging tracing: FORCE 70 69 $(call descend,$@) 71 70 72 71 bpf/%: FORCE ··· 101 100 kvm_stat: FORCE 102 101 $(call descend,kvm/$@) 103 102 104 - all: acpi cgroup cpupower gpio hv firewire liblockdep \ 103 + all: acpi cgroup counter cpupower gpio hv firewire liblockdep \ 105 104 perf selftests bootconfig spi turbostat usb \ 106 105 virtio vm bpf x86_energy_perf_policy \ 107 106 tmon freefall iio objtool kvm_stat wmi \ ··· 113 112 cpupower_install: 114 113 $(call descend,power/$(@:_install=),install) 115 114 116 - cgroup_install firewire_install gpio_install hv_install iio_install perf_install bootconfig_install spi_install usb_install virtio_install vm_install bpf_install objtool_install wmi_install pci_install debugging_install tracing_install: 115 + cgroup_install counter_install firewire_install gpio_install hv_install iio_install perf_install bootconfig_install spi_install usb_install virtio_install vm_install bpf_install objtool_install wmi_install pci_install debugging_install tracing_install: 117 116 $(call descend,$(@:_install=),install) 118 117 119 118 liblockdep_install: ··· 134 133 kvm_stat_install: 135 134 $(call descend,kvm/$(@:_install=),install) 136 135 137 - install: acpi_install cgroup_install cpupower_install gpio_install \ 136 + install: acpi_install cgroup_install counter_install cpupower_install gpio_install \ 138 137 hv_install firewire_install iio_install liblockdep_install \ 139 138 perf_install selftests_install turbostat_install usb_install \ 140 139 virtio_install vm_install bpf_install x86_energy_perf_policy_install \ ··· 148 147 cpupower_clean: 149 148 $(call descend,power/cpupower,clean) 150 149 151 - cgroup_clean hv_clean firewire_clean bootconfig_clean spi_clean usb_clean virtio_clean vm_clean wmi_clean bpf_clean iio_clean gpio_clean objtool_clean leds_clean pci_clean firmware_clean debugging_clean tracing_clean: 150 + cgroup_clean counter_clean hv_clean firewire_clean bootconfig_clean spi_clean usb_clean virtio_clean vm_clean wmi_clean bpf_clean iio_clean gpio_clean objtool_clean leds_clean pci_clean firmware_clean debugging_clean tracing_clean: 152 151 $(call descend,$(@:_clean=),clean) 153 152 154 153 liblockdep_clean: ··· 182 181 build_clean: 183 182 $(call descend,build,clean) 184 183 185 - clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean \ 184 + clean: acpi_clean cgroup_clean counter_clean cpupower_clean hv_clean firewire_clean \ 186 185 perf_clean selftests_clean turbostat_clean bootconfig_clean spi_clean usb_clean virtio_clean \ 187 186 vm_clean bpf_clean iio_clean x86_energy_perf_policy_clean tmon_clean \ 188 187 freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean \
+1
tools/counter/Build
··· 1 + counter_example-y += counter_example.o
+53
tools/counter/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + include ../scripts/Makefile.include 3 + 4 + bindir ?= /usr/bin 5 + 6 + ifeq ($(srctree),) 7 + srctree := $(patsubst %/,%,$(dir $(CURDIR))) 8 + srctree := $(patsubst %/,%,$(dir $(srctree))) 9 + endif 10 + 11 + # Do not use make's built-in rules 12 + # (this improves performance and avoids hard-to-debug behaviour); 13 + MAKEFLAGS += -r 14 + 15 + override CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include 16 + 17 + ALL_TARGETS := counter_example 18 + ALL_PROGRAMS := $(patsubst %,$(OUTPUT)%,$(ALL_TARGETS)) 19 + 20 + all: $(ALL_PROGRAMS) 21 + 22 + export srctree OUTPUT CC LD CFLAGS 23 + include $(srctree)/tools/build/Makefile.include 24 + 25 + # 26 + # We need the following to be outside of kernel tree 27 + # 28 + $(OUTPUT)include/linux/counter.h: ../../include/uapi/linux/counter.h 29 + mkdir -p $(OUTPUT)include/linux 2>&1 || true 30 + ln -sf $(CURDIR)/../../include/uapi/linux/counter.h $@ 31 + 32 + prepare: $(OUTPUT)include/linux/counter.h 33 + 34 + COUNTER_EXAMPLE := $(OUTPUT)counter_example.o 35 + $(COUNTER_EXAMPLE): prepare FORCE 36 + $(Q)$(MAKE) $(build)=counter_example 37 + $(OUTPUT)counter_example: $(COUNTER_EXAMPLE) 38 + $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ 39 + 40 + clean: 41 + rm -f $(ALL_PROGRAMS) 42 + rm -rf $(OUTPUT)include/linux/counter.h 43 + find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.d' -delete 44 + 45 + install: $(ALL_PROGRAMS) 46 + install -d -m 755 $(DESTDIR)$(bindir); \ 47 + for program in $(ALL_PROGRAMS); do \ 48 + install $$program $(DESTDIR)$(bindir); \ 49 + done 50 + 51 + FORCE: 52 + 53 + .PHONY: all install clean FORCE prepare
+92
tools/counter/counter_example.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* Counter - example userspace application 3 + * 4 + * The userspace application opens /dev/counter0, configures the 5 + * COUNTER_EVENT_INDEX event channel 0 to gather Count 0 count and Count 6 + * 1 count, and prints out the data as it becomes available on the 7 + * character device node. 8 + * 9 + * Copyright (C) 2021 William Breathitt Gray 10 + */ 11 + #include <errno.h> 12 + #include <fcntl.h> 13 + #include <linux/counter.h> 14 + #include <stdio.h> 15 + #include <string.h> 16 + #include <sys/ioctl.h> 17 + #include <unistd.h> 18 + 19 + static struct counter_watch watches[2] = { 20 + { 21 + /* Component data: Count 0 count */ 22 + .component.type = COUNTER_COMPONENT_COUNT, 23 + .component.scope = COUNTER_SCOPE_COUNT, 24 + .component.parent = 0, 25 + /* Event type: Index */ 26 + .event = COUNTER_EVENT_INDEX, 27 + /* Device event channel 0 */ 28 + .channel = 0, 29 + }, 30 + { 31 + /* Component data: Count 1 count */ 32 + .component.type = COUNTER_COMPONENT_COUNT, 33 + .component.scope = COUNTER_SCOPE_COUNT, 34 + .component.parent = 1, 35 + /* Event type: Index */ 36 + .event = COUNTER_EVENT_INDEX, 37 + /* Device event channel 0 */ 38 + .channel = 0, 39 + }, 40 + }; 41 + 42 + int main(void) 43 + { 44 + int fd; 45 + int ret; 46 + int i; 47 + struct counter_event event_data[2]; 48 + 49 + fd = open("/dev/counter0", O_RDWR); 50 + if (fd == -1) { 51 + perror("Unable to open /dev/counter0"); 52 + return 1; 53 + } 54 + 55 + for (i = 0; i < 2; i++) { 56 + ret = ioctl(fd, COUNTER_ADD_WATCH_IOCTL, watches + i); 57 + if (ret == -1) { 58 + fprintf(stderr, "Error adding watches[%d]: %s\n", i, 59 + strerror(errno)); 60 + return 1; 61 + } 62 + } 63 + ret = ioctl(fd, COUNTER_ENABLE_EVENTS_IOCTL); 64 + if (ret == -1) { 65 + perror("Error enabling events"); 66 + return 1; 67 + } 68 + 69 + for (;;) { 70 + ret = read(fd, event_data, sizeof(event_data)); 71 + if (ret == -1) { 72 + perror("Failed to read event data"); 73 + return 1; 74 + } 75 + 76 + if (ret != sizeof(event_data)) { 77 + fprintf(stderr, "Failed to read event data\n"); 78 + return -EIO; 79 + } 80 + 81 + printf("Timestamp 0: %llu\tCount 0: %llu\n" 82 + "Error Message 0: %s\n" 83 + "Timestamp 1: %llu\tCount 1: %llu\n" 84 + "Error Message 1: %s\n", 85 + event_data[0].timestamp, event_data[0].value, 86 + strerror(event_data[0].status), 87 + event_data[1].timestamp, event_data[1].value, 88 + strerror(event_data[1].status)); 89 + } 90 + 91 + return 0; 92 + }