1.. SPDX-License-Identifier: GPL-2.0 2 3=============================== 4The Linux kernel dpll subsystem 5=============================== 6 7DPLL 8==== 9 10PLL - Phase Locked Loop is an electronic circuit which syntonizes clock 11signal of a device with an external clock signal. Effectively enabling 12device to run on the same clock signal beat as provided on a PLL input. 13 14DPLL - Digital Phase Locked Loop is an integrated circuit which in 15addition to plain PLL behavior incorporates a digital phase detector 16and may have digital divider in the loop. As a result, the frequency on 17DPLL's input and output may be configurable. 18 19Subsystem 20========= 21 22The main purpose of dpll subsystem is to provide general interface 23to configure devices that use any kind of Digital PLL and could use 24different sources of input signal to synchronize to, as well as 25different types of outputs. 26The main interface is NETLINK_GENERIC based protocol with an event 27monitoring multicast group defined. 28 29Device object 30============= 31 32Single dpll device object means single Digital PLL circuit and bunch of 33connected pins. 34It reports the supported modes of operation and current status to the 35user in response to the `do` request of netlink command 36``DPLL_CMD_DEVICE_GET`` and list of dplls registered in the subsystem 37with `dump` netlink request of the same command. 38Changing the configuration of dpll device is done with `do` request of 39netlink ``DPLL_CMD_DEVICE_SET`` command. 40A device handle is ``DPLL_A_ID``, it shall be provided to get or set 41configuration of particular device in the system. It can be obtained 42with a ``DPLL_CMD_DEVICE_GET`` `dump` request or 43a ``DPLL_CMD_DEVICE_ID_GET`` `do` request, where the one must provide 44attributes that result in single device match. 45 46Pin object 47========== 48 49A pin is amorphic object which represents either input or output, it 50could be internal component of the device, as well as externally 51connected. 52The number of pins per dpll vary, but usually multiple pins shall be 53provided for a single dpll device. 54Pin's properties, capabilities and status is provided to the user in 55response to `do` request of netlink ``DPLL_CMD_PIN_GET`` command. 56It is also possible to list all the pins that were registered in the 57system with `dump` request of ``DPLL_CMD_PIN_GET`` command. 58Configuration of a pin can be changed by `do` request of netlink 59``DPLL_CMD_PIN_SET`` command. 60Pin handle is a ``DPLL_A_PIN_ID``, it shall be provided to get or set 61configuration of particular pin in the system. It can be obtained with 62``DPLL_CMD_PIN_GET`` `dump` request or ``DPLL_CMD_PIN_ID_GET`` `do` 63request, where user provides attributes that result in single pin match. 64 65Pin selection 66============= 67 68In general, selected pin (the one which signal is driving the dpll 69device) can be obtained from ``DPLL_A_PIN_STATE`` attribute, and only 70one pin shall be in ``DPLL_PIN_STATE_CONNECTED`` state for any dpll 71device. 72 73Pin selection can be done either manually or automatically, depending 74on hardware capabilities and active dpll device work mode 75(``DPLL_A_MODE`` attribute). The consequence is that there are 76differences for each mode in terms of available pin states, as well as 77for the states the user can request for a dpll device. 78 79In manual mode (``DPLL_MODE_MANUAL``) the user can request or receive 80one of following pin states: 81 82- ``DPLL_PIN_STATE_CONNECTED`` - the pin is used to drive dpll device 83- ``DPLL_PIN_STATE_DISCONNECTED`` - the pin is not used to drive dpll 84 device 85 86In automatic mode (``DPLL_MODE_AUTOMATIC``) the user can request or 87receive one of following pin states: 88 89- ``DPLL_PIN_STATE_SELECTABLE`` - the pin shall be considered as valid 90 input for automatic selection algorithm 91- ``DPLL_PIN_STATE_DISCONNECTED`` - the pin shall be not considered as 92 a valid input for automatic selection algorithm 93 94In automatic mode (``DPLL_MODE_AUTOMATIC``) the user can only receive 95pin state ``DPLL_PIN_STATE_CONNECTED`` once automatic selection 96algorithm locks a dpll device with one of the inputs. 97 98Shared pins 99=========== 100 101A single pin object can be attached to multiple dpll devices. 102Then there are two groups of configuration knobs: 103 1041) Set on a pin - the configuration affects all dpll devices pin is 105 registered to (i.e., ``DPLL_A_PIN_FREQUENCY``), 1062) Set on a pin-dpll tuple - the configuration affects only selected 107 dpll device (i.e., ``DPLL_A_PIN_PRIO``, ``DPLL_A_PIN_STATE``, 108 ``DPLL_A_PIN_DIRECTION``). 109 110MUX-type pins 111============= 112 113A pin can be MUX-type, it aggregates child pins and serves as a pin 114multiplexer. One or more pins are registered with MUX-type instead of 115being directly registered to a dpll device. 116Pins registered with a MUX-type pin provide user with additional nested 117attribute ``DPLL_A_PIN_PARENT_PIN`` for each parent they were registered 118with. 119If a pin was registered with multiple parent pins, they behave like a 120multiple output multiplexer. In this case output of a 121``DPLL_CMD_PIN_GET`` would contain multiple pin-parent nested 122attributes with current state related to each parent, like: 123 124'pin': [{{ 125 'clock-id': 282574471561216, 126 'module-name': 'ice', 127 'capabilities': 4, 128 'id': 13, 129 'parent-pin': [ 130 {'parent-id': 2, 'state': 'connected'}, 131 {'parent-id': 3, 'state': 'disconnected'} 132 ], 133 'type': 'synce-eth-port' 134 }}] 135 136Only one child pin can provide its signal to the parent MUX-type pin at 137a time, the selection is done by requesting change of a child pin state 138on desired parent, with the use of ``DPLL_A_PIN_PARENT`` nested 139attribute. Example of netlink `set state on parent pin` message format: 140 141 ========================== ============================================= 142 ``DPLL_A_PIN_ID`` child pin id 143 ``DPLL_A_PIN_PARENT_PIN`` nested attribute for requesting configuration 144 related to parent pin 145 ``DPLL_A_PIN_PARENT_ID`` parent pin id 146 ``DPLL_A_PIN_STATE`` requested pin state on parent 147 ========================== ============================================= 148 149Pin priority 150============ 151 152Some devices might offer a capability of automatic pin selection mode 153(enum value ``DPLL_MODE_AUTOMATIC`` of ``DPLL_A_MODE`` attribute). 154Usually, automatic selection is performed on the hardware level, which 155means only pins directly connected to the dpll can be used for automatic 156input pin selection. 157In automatic selection mode, the user cannot manually select a input 158pin for the device, instead the user shall provide all directly 159connected pins with a priority ``DPLL_A_PIN_PRIO``, the device would 160pick a highest priority valid signal and use it to control the DPLL 161device. Example of netlink `set priority on parent pin` message format: 162 163 ============================ ============================================= 164 ``DPLL_A_PIN_ID`` configured pin id 165 ``DPLL_A_PIN_PARENT_DEVICE`` nested attribute for requesting configuration 166 related to parent dpll device 167 ``DPLL_A_PIN_PARENT_ID`` parent dpll device id 168 ``DPLL_A_PIN_PRIO`` requested pin prio on parent dpll 169 ============================ ============================================= 170 171Child pin of MUX-type pin is not capable of automatic input pin selection, 172in order to configure active input of a MUX-type pin, the user needs to 173request desired pin state of the child pin on the parent pin, 174as described in the ``MUX-type pins`` chapter. 175 176Configuration commands group 177============================ 178 179Configuration commands are used to get information about registered 180dpll devices (and pins), as well as set configuration of device or pins. 181As dpll devices must be abstracted and reflect real hardware, 182there is no way to add new dpll device via netlink from user space and 183each device should be registered by its driver. 184 185All netlink commands require ``GENL_ADMIN_PERM``. This is to prevent 186any spamming/DoS from unauthorized userspace applications. 187 188List of netlink commands with possible attributes 189================================================= 190 191Constants identifying command types for dpll device uses a 192``DPLL_CMD_`` prefix and suffix according to command purpose. 193The dpll device related attributes use a ``DPLL_A_`` prefix and 194suffix according to attribute purpose. 195 196 ==================================== ================================= 197 ``DPLL_CMD_DEVICE_ID_GET`` command to get device ID 198 ``DPLL_A_MODULE_NAME`` attr module name of registerer 199 ``DPLL_A_CLOCK_ID`` attr Unique Clock Identifier 200 (EUI-64), as defined by the 201 IEEE 1588 standard 202 ``DPLL_A_TYPE`` attr type of dpll device 203 ==================================== ================================= 204 205 ==================================== ================================= 206 ``DPLL_CMD_DEVICE_GET`` command to get device info or 207 dump list of available devices 208 ``DPLL_A_ID`` attr unique dpll device ID 209 ``DPLL_A_MODULE_NAME`` attr module name of registerer 210 ``DPLL_A_CLOCK_ID`` attr Unique Clock Identifier 211 (EUI-64), as defined by the 212 IEEE 1588 standard 213 ``DPLL_A_MODE`` attr selection mode 214 ``DPLL_A_MODE_SUPPORTED`` attr available selection modes 215 ``DPLL_A_LOCK_STATUS`` attr dpll device lock status 216 ``DPLL_A_TEMP`` attr device temperature info 217 ``DPLL_A_TYPE`` attr type of dpll device 218 ==================================== ================================= 219 220 ==================================== ================================= 221 ``DPLL_CMD_DEVICE_SET`` command to set dpll device config 222 ``DPLL_A_ID`` attr internal dpll device index 223 ``DPLL_A_MODE`` attr selection mode to configure 224 ==================================== ================================= 225 226Constants identifying command types for pins uses a 227``DPLL_CMD_PIN_`` prefix and suffix according to command purpose. 228The pin related attributes use a ``DPLL_A_PIN_`` prefix and suffix 229according to attribute purpose. 230 231 ==================================== ================================= 232 ``DPLL_CMD_PIN_ID_GET`` command to get pin ID 233 ``DPLL_A_PIN_MODULE_NAME`` attr module name of registerer 234 ``DPLL_A_PIN_CLOCK_ID`` attr Unique Clock Identifier 235 (EUI-64), as defined by the 236 IEEE 1588 standard 237 ``DPLL_A_PIN_BOARD_LABEL`` attr pin board label provided 238 by registerer 239 ``DPLL_A_PIN_PANEL_LABEL`` attr pin panel label provided 240 by registerer 241 ``DPLL_A_PIN_PACKAGE_LABEL`` attr pin package label provided 242 by registerer 243 ``DPLL_A_PIN_TYPE`` attr type of a pin 244 ==================================== ================================= 245 246 ==================================== ================================== 247 ``DPLL_CMD_PIN_GET`` command to get pin info or dump 248 list of available pins 249 ``DPLL_A_PIN_ID`` attr unique a pin ID 250 ``DPLL_A_PIN_MODULE_NAME`` attr module name of registerer 251 ``DPLL_A_PIN_CLOCK_ID`` attr Unique Clock Identifier 252 (EUI-64), as defined by the 253 IEEE 1588 standard 254 ``DPLL_A_PIN_BOARD_LABEL`` attr pin board label provided 255 by registerer 256 ``DPLL_A_PIN_PANEL_LABEL`` attr pin panel label provided 257 by registerer 258 ``DPLL_A_PIN_PACKAGE_LABEL`` attr pin package label provided 259 by registerer 260 ``DPLL_A_PIN_TYPE`` attr type of a pin 261 ``DPLL_A_PIN_FREQUENCY`` attr current frequency of a pin 262 ``DPLL_A_PIN_FREQUENCY_SUPPORTED`` nested attr provides supported 263 frequencies 264 ``DPLL_A_PIN_ANY_FREQUENCY_MIN`` attr minimum value of frequency 265 ``DPLL_A_PIN_ANY_FREQUENCY_MAX`` attr maximum value of frequency 266 ``DPLL_A_PIN_PARENT_DEVICE`` nested attr for each parent device 267 the pin is connected with 268 ``DPLL_A_PIN_PARENT_ID`` attr parent dpll device id 269 ``DPLL_A_PIN_PRIO`` attr priority of pin on the 270 dpll device 271 ``DPLL_A_PIN_STATE`` attr state of pin on the parent 272 dpll device 273 ``DPLL_A_PIN_DIRECTION`` attr direction of a pin on the 274 parent dpll device 275 ``DPLL_A_PIN_PARENT_PIN`` nested attr for each parent pin 276 the pin is connected with 277 ``DPLL_A_PIN_PARENT_ID`` attr parent pin id 278 ``DPLL_A_PIN_STATE`` attr state of pin on the parent 279 pin 280 ``DPLL_A_PIN_CAPABILITIES`` attr bitmask of pin capabilities 281 ==================================== ================================== 282 283 ==================================== ================================= 284 ``DPLL_CMD_PIN_SET`` command to set pins configuration 285 ``DPLL_A_PIN_ID`` attr unique a pin ID 286 ``DPLL_A_PIN_FREQUENCY`` attr requested frequency of a pin 287 ``DPLL_A_PIN_PARENT_DEVICE`` nested attr for each parent dpll 288 device configuration request 289 ``DPLL_A_PIN_PARENT_ID`` attr parent dpll device id 290 ``DPLL_A_PIN_DIRECTION`` attr requested direction of a pin 291 ``DPLL_A_PIN_PRIO`` attr requested priority of pin on 292 the dpll device 293 ``DPLL_A_PIN_STATE`` attr requested state of pin on 294 the dpll device 295 ``DPLL_A_PIN_PARENT_PIN`` nested attr for each parent pin 296 configuration request 297 ``DPLL_A_PIN_PARENT_ID`` attr parent pin id 298 ``DPLL_A_PIN_STATE`` attr requested state of pin on 299 parent pin 300 ==================================== ================================= 301 302Netlink dump requests 303===================== 304 305The ``DPLL_CMD_DEVICE_GET`` and ``DPLL_CMD_PIN_GET`` commands are 306capable of dump type netlink requests, in which case the response is in 307the same format as for their ``do`` request, but every device or pin 308registered in the system is returned. 309 310SET commands format 311=================== 312 313``DPLL_CMD_DEVICE_SET`` - to target a dpll device, the user provides 314``DPLL_A_ID``, which is unique identifier of dpll device in the system, 315as well as parameter being configured (``DPLL_A_MODE``). 316 317``DPLL_CMD_PIN_SET`` - to target a pin user must provide a 318``DPLL_A_PIN_ID``, which is unique identifier of a pin in the system. 319Also configured pin parameters must be added. 320If ``DPLL_A_PIN_FREQUENCY`` is configured, this affects all the dpll 321devices that are connected with the pin, that is why frequency attribute 322shall not be enclosed in ``DPLL_A_PIN_PARENT_DEVICE``. 323Other attributes: ``DPLL_A_PIN_PRIO``, ``DPLL_A_PIN_STATE`` or 324``DPLL_A_PIN_DIRECTION`` must be enclosed in 325``DPLL_A_PIN_PARENT_DEVICE`` as their configuration relates to only one 326of parent dplls, targeted by ``DPLL_A_PIN_PARENT_ID`` attribute which is 327also required inside that nest. 328For MUX-type pins the ``DPLL_A_PIN_STATE`` attribute is configured in 329similar way, by enclosing required state in ``DPLL_A_PIN_PARENT_PIN`` 330nested attribute and targeted parent pin id in ``DPLL_A_PIN_PARENT_ID``. 331 332In general, it is possible to configure multiple parameters at once, but 333internally each parameter change will be invoked separately, where order 334of configuration is not guaranteed by any means. 335 336Configuration pre-defined enums 337=============================== 338 339.. kernel-doc:: include/uapi/linux/dpll.h 340 341Notifications 342============= 343 344dpll device can provide notifications regarding status changes of the 345device, i.e. lock status changes, input/output changes or other alarms. 346There is one multicast group that is used to notify user-space apps via 347netlink socket: ``DPLL_MCGRP_MONITOR`` 348 349Notifications messages: 350 351 ============================== ===================================== 352 ``DPLL_CMD_DEVICE_CREATE_NTF`` dpll device was created 353 ``DPLL_CMD_DEVICE_DELETE_NTF`` dpll device was deleted 354 ``DPLL_CMD_DEVICE_CHANGE_NTF`` dpll device has changed 355 ``DPLL_CMD_PIN_CREATE_NTF`` dpll pin was created 356 ``DPLL_CMD_PIN_DELETE_NTF`` dpll pin was deleted 357 ``DPLL_CMD_PIN_CHANGE_NTF`` dpll pin has changed 358 ============================== ===================================== 359 360Events format is the same as for the corresponding get command. 361Format of ``DPLL_CMD_DEVICE_`` events is the same as response of 362``DPLL_CMD_DEVICE_GET``. 363Format of ``DPLL_CMD_PIN_`` events is same as response of 364``DPLL_CMD_PIN_GET``. 365 366Device driver implementation 367============================ 368 369Device is allocated by dpll_device_get() call. Second call with the 370same arguments will not create new object but provides pointer to 371previously created device for given arguments, it also increases 372refcount of that object. 373Device is deallocated by dpll_device_put() call, which first 374decreases the refcount, once refcount is cleared the object is 375destroyed. 376 377Device should implement set of operations and register device via 378dpll_device_register() at which point it becomes available to the 379users. Multiple driver instances can obtain reference to it with 380dpll_device_get(), as well as register dpll device with their own 381ops and priv. 382 383The pins are allocated separately with dpll_pin_get(), it works 384similarly to dpll_device_get(). Function first creates object and then 385for each call with the same arguments only the object refcount 386increases. Also dpll_pin_put() works similarly to dpll_device_put(). 387 388A pin can be registered with parent dpll device or parent pin, depending 389on hardware needs. Each registration requires registerer to provide set 390of pin callbacks, and private data pointer for calling them: 391 392- dpll_pin_register() - register pin with a dpll device, 393- dpll_pin_on_pin_register() - register pin with another MUX type pin. 394 395Notifications of adding or removing dpll devices are created within 396subsystem itself. 397Notifications about registering/deregistering pins are also invoked by 398the subsystem. 399Notifications about status changes either of dpll device or a pin are 400invoked in two ways: 401 402- after successful change was requested on dpll subsystem, the subsystem 403 calls corresponding notification, 404- requested by device driver with dpll_device_change_ntf() or 405 dpll_pin_change_ntf() when driver informs about the status change. 406 407The device driver using dpll interface is not required to implement all 408the callback operation. Nevertheless, there are few required to be 409implemented. 410Required dpll device level callback operations: 411 412- ``.mode_get``, 413- ``.lock_status_get``. 414 415Required pin level callback operations: 416 417- ``.state_on_dpll_get`` (pins registered with dpll device), 418- ``.state_on_pin_get`` (pins registered with parent pin), 419- ``.direction_get``. 420 421Every other operation handler is checked for existence and 422``-EOPNOTSUPP`` is returned in case of absence of specific handler. 423 424The simplest implementation is in the OCP TimeCard driver. The ops 425structures are defined like this: 426 427.. code-block:: c 428 static const struct dpll_device_ops dpll_ops = { 429 .lock_status_get = ptp_ocp_dpll_lock_status_get, 430 .mode_get = ptp_ocp_dpll_mode_get, 431 .mode_supported = ptp_ocp_dpll_mode_supported, 432 }; 433 434 static const struct dpll_pin_ops dpll_pins_ops = { 435 .frequency_get = ptp_ocp_dpll_frequency_get, 436 .frequency_set = ptp_ocp_dpll_frequency_set, 437 .direction_get = ptp_ocp_dpll_direction_get, 438 .direction_set = ptp_ocp_dpll_direction_set, 439 .state_on_dpll_get = ptp_ocp_dpll_state_get, 440 }; 441 442The registration part is then looks like this part: 443 444.. code-block:: c 445 clkid = pci_get_dsn(pdev); 446 bp->dpll = dpll_device_get(clkid, 0, THIS_MODULE); 447 if (IS_ERR(bp->dpll)) { 448 err = PTR_ERR(bp->dpll); 449 dev_err(&pdev->dev, "dpll_device_alloc failed\n"); 450 goto out; 451 } 452 453 err = dpll_device_register(bp->dpll, DPLL_TYPE_PPS, &dpll_ops, bp); 454 if (err) 455 goto out; 456 457 for (i = 0; i < OCP_SMA_NUM; i++) { 458 bp->sma[i].dpll_pin = dpll_pin_get(clkid, i, THIS_MODULE, &bp->sma[i].dpll_prop); 459 if (IS_ERR(bp->sma[i].dpll_pin)) { 460 err = PTR_ERR(bp->dpll); 461 goto out_dpll; 462 } 463 464 err = dpll_pin_register(bp->dpll, bp->sma[i].dpll_pin, &dpll_pins_ops, 465 &bp->sma[i]); 466 if (err) { 467 dpll_pin_put(bp->sma[i].dpll_pin); 468 goto out_dpll; 469 } 470 } 471 472In the error path we have to rewind every allocation in the reverse order: 473 474.. code-block:: c 475 while (i) { 476 --i; 477 dpll_pin_unregister(bp->dpll, bp->sma[i].dpll_pin, &dpll_pins_ops, &bp->sma[i]); 478 dpll_pin_put(bp->sma[i].dpll_pin); 479 } 480 dpll_device_put(bp->dpll); 481 482More complex example can be found in Intel's ICE driver or nVidia's mlx5 driver. 483 484SyncE enablement 485================ 486For SyncE enablement it is required to allow control over dpll device 487for a software application which monitors and configures the inputs of 488dpll device in response to current state of a dpll device and its 489inputs. 490In such scenario, dpll device input signal shall be also configurable 491to drive dpll with signal recovered from the PHY netdevice. 492This is done by exposing a pin to the netdevice - attaching pin to the 493netdevice itself with 494``netdev_dpll_pin_set(struct net_device *dev, struct dpll_pin *dpll_pin)``. 495Exposed pin id handle ``DPLL_A_PIN_ID`` is then identifiable by the user 496as it is attached to rtnetlink respond to get ``RTM_NEWLINK`` command in 497nested attribute ``IFLA_DPLL_PIN``. 498