| 1 | |
| 2 |
|
| 3 | ===============================
|
| 4 | The Linux kernel dpll subsystem
|
| 5 | ===============================
|
| 6 |
|
| 7 | DPLL
|
| 8 | ====
|
| 9 |
|
| 10 | PLL - Phase Locked Loop is an electronic circuit which syntonizes clock
|
| 11 | signal of a device with an external clock signal. Effectively enabling
|
| 12 | device to run on the same clock signal beat as provided on a PLL input.
|
| 13 |
|
| 14 | DPLL - Digital Phase Locked Loop is an integrated circuit which in
|
| 15 | addition to plain PLL behavior incorporates a digital phase detector
|
| 16 | and may have digital divider in the loop. As a result, the frequency on
|
| 17 | DPLL's input and output may be configurable.
|
| 18 |
|
| 19 | Subsystem
|
| 20 | =========
|
| 21 |
|
| 22 | The main purpose of dpll subsystem is to provide general interface
|
| 23 | to configure devices that use any kind of Digital PLL and could use
|
| 24 | different sources of input signal to synchronize to, as well as
|
| 25 | different types of outputs.
|
| 26 | The main interface is NETLINK_GENERIC based protocol with an event
|
| 27 | monitoring multicast group defined.
|
| 28 |
|
| 29 | Device object
|
| 30 | =============
|
| 31 |
|
| 32 | Single dpll device object means single Digital PLL circuit and bunch of
|
| 33 | connected pins.
|
| 34 | It reports the supported modes of operation and current status to the
|
| 35 | user in response to the `do` request of netlink command
|
| 36 | ``DPLL_CMD_DEVICE_GET`` and list of dplls registered in the subsystem
|
| 37 | with `dump` netlink request of the same command.
|
| 38 | Changing the configuration of dpll device is done with `do` request of
|
| 39 | netlink ``DPLL_CMD_DEVICE_SET`` command.
|
| 40 | A device handle is ``DPLL_A_ID``, it shall be provided to get or set
|
| 41 | configuration of particular device in the system. It can be obtained
|
| 42 | with a ``DPLL_CMD_DEVICE_GET`` `dump` request or
|
| 43 | a ``DPLL_CMD_DEVICE_ID_GET`` `do` request, where the one must provide
|
| 44 | attributes that result in single device match.
|
| 45 |
|
| 46 | Pin object
|
| 47 | ==========
|
| 48 |
|
| 49 | A pin is amorphic object which represents either input or output, it
|
| 50 | could be internal component of the device, as well as externally
|
| 51 | connected.
|
| 52 | The number of pins per dpll vary, but usually multiple pins shall be
|
| 53 | provided for a single dpll device.
|
| 54 | Pin's properties, capabilities and status is provided to the user in
|
| 55 | response to `do` request of netlink ``DPLL_CMD_PIN_GET`` command.
|
| 56 | It is also possible to list all the pins that were registered in the
|
| 57 | system with `dump` request of ``DPLL_CMD_PIN_GET`` command.
|
| 58 | Configuration of a pin can be changed by `do` request of netlink
|
| 59 | ``DPLL_CMD_PIN_SET`` command.
|
| 60 | Pin handle is a ``DPLL_A_PIN_ID``, it shall be provided to get or set
|
| 61 | configuration 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`
|
| 63 | request, where user provides attributes that result in single pin match.
|
| 64 |
|
| 65 | Pin selection
|
| 66 | =============
|
| 67 |
|
| 68 | Pin state (``DPLL_A_PIN_STATE``) reflects the administrative intent set
|
| 69 | by the user. Pin operational state (``DPLL_A_PIN_OPERSTATE``) reflects
|
| 70 | what the hardware is actually doing with the pin.
|
| 71 |
|
| 72 | Pin selection can be done either manually or automatically, depending
|
| 73 | on hardware capabilities and active dpll device work mode
|
| 74 | (``DPLL_A_MODE`` attribute). The consequence is that there are
|
| 75 | differences for each mode in terms of available pin states the user can
|
| 76 | request for a dpll device.
|
| 77 |
|
| 78 | In manual mode (``DPLL_MODE_MANUAL``) the user can request one of
|
| 79 | following pin states:
|
| 80 |
|
| 81 | - ``DPLL_PIN_STATE_CONNECTED`` - the pin is selected to drive dpll
|
| 82 | device
|
| 83 | - ``DPLL_PIN_STATE_DISCONNECTED`` - the pin is not selected to drive
|
| 84 | dpll device
|
| 85 |
|
| 86 | In automatic mode (``DPLL_MODE_AUTOMATIC``) the user can request one of
|
| 87 | 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 |
|
| 94 | Pins that have the ``DPLL_PIN_CAPABILITIES_STATE_CONNECTED_OVERRIDE``
|
| 95 | capability can additionally be set to ``DPLL_PIN_STATE_CONNECTED`` in
|
| 96 | automatic mode, overriding the active input selection. This is useful
|
| 97 | for automatic-only DPLL devices where mode cannot be switched to manual.
|
| 98 | When such a pin is disconnected, the device returns to automatic input
|
| 99 | selection.
|
| 100 |
|
| 101 | The actual hardware status of a pin is reported via the operational
|
| 102 | state (``DPLL_A_PIN_OPERSTATE``) attribute nested under the parent
|
| 103 | device:
|
| 104 |
|
| 105 | - ``DPLL_PIN_OPERSTATE_ACTIVE`` - pin is qualified and actively used
|
| 106 | by the DPLL
|
| 107 | - ``DPLL_PIN_OPERSTATE_STANDBY`` - pin is qualified but not actively
|
| 108 | used by the DPLL
|
| 109 | - ``DPLL_PIN_OPERSTATE_NO_SIGNAL`` - pin does not have a valid signal
|
| 110 | - ``DPLL_PIN_OPERSTATE_QUAL_FAILED`` - pin signal failed qualification
|
| 111 | checks
|
| 112 |
|
| 113 | Shared pins
|
| 114 | ===========
|
| 115 |
|
| 116 | A single pin object can be attached to multiple dpll devices.
|
| 117 | Then there are two groups of configuration knobs:
|
| 118 |
|
| 119 | 1) Set on a pin - the configuration is a property of the pin itself and
|
| 120 | applies to all dpll devices the pin is registered with
|
| 121 | (i.e., ``DPLL_A_PIN_FREQUENCY``),
|
| 122 | 2) Set on a pin-dpll tuple - the configuration affects only selected
|
| 123 | dpll device (i.e., ``DPLL_A_PIN_PRIO``, ``DPLL_A_PIN_STATE``,
|
| 124 | ``DPLL_A_PIN_DIRECTION``).
|
| 125 |
|
| 126 | MUX-type pins
|
| 127 | =============
|
| 128 |
|
| 129 | A pin can be MUX-type, it aggregates child pins and serves as a pin
|
| 130 | multiplexer. One or more pins are registered with MUX-type instead of
|
| 131 | being directly registered to a dpll device.
|
| 132 | Pins registered with a MUX-type pin provide user with additional nested
|
| 133 | attribute ``DPLL_A_PIN_PARENT_PIN`` for each parent they were registered
|
| 134 | with.
|
| 135 | If a pin was registered with multiple parent pins, they behave like a
|
| 136 | multiple output multiplexer. In this case output of a
|
| 137 | ``DPLL_CMD_PIN_GET`` would contain multiple pin-parent nested
|
| 138 | attributes with current state related to each parent, like::
|
| 139 |
|
| 140 | 'pin': [{{
|
| 141 | 'clock-id': 282574471561216,
|
| 142 | 'module-name': 'ice',
|
| 143 | 'capabilities': 4,
|
| 144 | 'id': 13,
|
| 145 | 'parent-pin': [
|
| 146 | {'parent-id': 2, 'state': 'connected'},
|
| 147 | {'parent-id': 3, 'state': 'disconnected'}
|
| 148 | ],
|
| 149 | 'type': 'synce-eth-port'
|
| 150 | }}]
|
| 151 |
|
| 152 | Only one child pin can provide its signal to the parent MUX-type pin at
|
| 153 | a time, the selection is done by requesting change of a child pin state
|
| 154 | on desired parent, with the use of ``DPLL_A_PIN_PARENT`` nested
|
| 155 | attribute. Example of netlink `set state on parent pin` message format:
|
| 156 |
|
| 157 | ========================== =============================================
|
| 158 | ``DPLL_A_PIN_ID`` child pin id
|
| 159 | ``DPLL_A_PIN_PARENT_PIN`` nested attribute for requesting configuration
|
| 160 | related to parent pin
|
| 161 | ``DPLL_A_PIN_PARENT_ID`` parent pin id
|
| 162 | ``DPLL_A_PIN_STATE`` requested pin state on parent
|
| 163 | ========================== =============================================
|
| 164 |
|
| 165 | Pin priority
|
| 166 | ============
|
| 167 |
|
| 168 | Some devices might offer a capability of automatic pin selection mode
|
| 169 | (enum value ``DPLL_MODE_AUTOMATIC`` of ``DPLL_A_MODE`` attribute).
|
| 170 | Usually, automatic selection is performed on the hardware level, which
|
| 171 | means only pins directly connected to the dpll can be used for automatic
|
| 172 | input pin selection.
|
| 173 | In automatic selection mode, the user cannot manually select a input
|
| 174 | pin for the device, instead the user shall provide all directly
|
| 175 | connected pins with a priority ``DPLL_A_PIN_PRIO``, the device would
|
| 176 | pick a highest priority valid signal and use it to control the DPLL
|
| 177 | device. Example of netlink `set priority on parent pin` message format:
|
| 178 |
|
| 179 | ============================ =============================================
|
| 180 | ``DPLL_A_PIN_ID`` configured pin id
|
| 181 | ``DPLL_A_PIN_PARENT_DEVICE`` nested attribute for requesting configuration
|
| 182 | related to parent dpll device
|
| 183 | ``DPLL_A_PIN_PARENT_ID`` parent dpll device id
|
| 184 | ``DPLL_A_PIN_PRIO`` requested pin prio on parent dpll
|
| 185 | ============================ =============================================
|
| 186 |
|
| 187 | Child pin of MUX-type pin is not capable of automatic input pin selection,
|
| 188 | in order to configure active input of a MUX-type pin, the user needs to
|
| 189 | request desired pin state of the child pin on the parent pin,
|
| 190 | as described in the ``MUX-type pins`` chapter.
|
| 191 |
|
| 192 | Phase offset measurement and adjustment
|
| 193 | ========================================
|
| 194 |
|
| 195 | Device may provide ability to measure a phase difference between signals
|
| 196 | on a pin and its parent dpll device. If pin-dpll phase offset measurement
|
| 197 | is supported, it shall be provided with ``DPLL_A_PIN_PHASE_OFFSET``
|
| 198 | attribute for each parent dpll device. The reported phase offset may be
|
| 199 | computed as the average of prior values and the current measurement, using
|
| 200 | the following formula:
|
| 201 |
|
| 202 | .. math::
|
| 203 | curr\_avg = prev\_avg * \frac{2^N-1}{2^N} + new\_val * \frac{1}{2^N}
|
| 204 |
|
| 205 | where `curr_avg` is the current reported phase offset, `prev_avg` is the
|
| 206 | previously reported value, `new_val` is the current measurement, and `N` is
|
| 207 | the averaging factor. Configured averaging factor value is provided with
|
| 208 | ``DPLL_A_PHASE_OFFSET_AVG_FACTOR`` attribute of a device and value change can
|
| 209 | be requested with the same attribute with ``DPLL_CMD_DEVICE_SET`` command.
|
| 210 |
|
| 211 | ================================== ======================================
|
| 212 | ``DPLL_A_PHASE_OFFSET_AVG_FACTOR`` attr configured value of phase offset
|
| 213 | averaging factor
|
| 214 | ================================== ======================================
|
| 215 |
|
| 216 | Device may also provide ability to adjust a signal phase on a pin.
|
| 217 | If pin phase adjustment is supported, minimal and maximal values and
|
| 218 | granularity that pin handle shall be provided to the user on
|
| 219 | ``DPLL_CMD_PIN_GET`` respond with ``DPLL_A_PIN_PHASE_ADJUST_MIN``,
|
| 220 | ``DPLL_A_PIN_PHASE_ADJUST_MAX`` and ``DPLL_A_PIN_PHASE_ADJUST_GRAN``
|
| 221 | attributes. Configured phase adjust value is provided with
|
| 222 | ``DPLL_A_PIN_PHASE_ADJUST`` attribute of a pin, and value change can be
|
| 223 | requested with the same attribute with ``DPLL_CMD_PIN_SET`` command.
|
| 224 |
|
| 225 | ================================ ==========================================
|
| 226 | ``DPLL_A_PIN_ID`` configured pin id
|
| 227 | ``DPLL_A_PIN_PHASE_ADJUST_GRAN`` attr granularity of phase adjustment value
|
| 228 | ``DPLL_A_PIN_PHASE_ADJUST_MIN`` attr minimum value of phase adjustment
|
| 229 | ``DPLL_A_PIN_PHASE_ADJUST_MAX`` attr maximum value of phase adjustment
|
| 230 | ``DPLL_A_PIN_PHASE_ADJUST`` attr configured value of phase
|
| 231 | adjustment on parent dpll device
|
| 232 | ``DPLL_A_PIN_PARENT_DEVICE`` nested attribute for requesting
|
| 233 | configuration on given parent dpll
|
| 234 | device
|
| 235 | ``DPLL_A_PIN_PARENT_ID`` parent dpll device id
|
| 236 | ``DPLL_A_PIN_PHASE_OFFSET`` attr measured phase difference
|
| 237 | between a pin and parent dpll device
|
| 238 | ================================ ==========================================
|
| 239 |
|
| 240 | All phase related values are provided in pico seconds, which represents
|
| 241 | time difference between signals phase. The negative value means that
|
| 242 | phase of signal on pin is earlier in time than dpll's signal. Positive
|
| 243 | value means that phase of signal on pin is later in time than signal of
|
| 244 | a dpll.
|
| 245 |
|
| 246 | Phase adjust (also min and max) values are integers, but measured phase
|
| 247 | offset values are fractional with 3-digit decimal places and shell be
|
| 248 | divided with ``DPLL_PIN_PHASE_OFFSET_DIVIDER`` to get integer part and
|
| 249 | modulo divided to get fractional part.
|
| 250 |
|
| 251 | Phase offset monitor
|
| 252 | ====================
|
| 253 |
|
| 254 | Phase offset measurement is typically performed against the current active
|
| 255 | source. However, some DPLL (Digital Phase-Locked Loop) devices may offer
|
| 256 | the capability to monitor phase offsets across all available inputs.
|
| 257 | The attribute and current feature state shall be included in the response
|
| 258 | message of the ``DPLL_CMD_DEVICE_GET`` command for supported DPLL devices.
|
| 259 | In such cases, users can also control the feature using the
|
| 260 | ``DPLL_CMD_DEVICE_SET`` command by setting the ``enum dpll_feature_state``
|
| 261 | values for the attribute.
|
| 262 | Once enabled the phase offset measurements for the input shall be returned
|
| 263 | in the ``DPLL_A_PIN_PHASE_OFFSET`` attribute.
|
| 264 |
|
| 265 | =============================== ========================
|
| 266 | ``DPLL_A_PHASE_OFFSET_MONITOR`` attr state of a feature
|
| 267 | =============================== ========================
|
| 268 |
|
| 269 | Fractional frequency offset
|
| 270 | ===========================
|
| 271 |
|
| 272 | The fractional frequency offset (FFO) is reported through two attributes
|
| 273 | that carry the same measurement at different precisions:
|
| 274 |
|
| 275 | - ``DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET`` in PPM (parts per million)
|
| 276 | - ``DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET_PPT`` in PPT (parts per trillion)
|
| 277 |
|
| 278 | Both attributes appear at the top level of a pin and inside each
|
| 279 | ``pin-parent-device`` nest. Two FFO types are defined:
|
| 280 |
|
| 281 | - ``DPLL_FFO_PORT_RXTX_RATE`` - RX vs TX symbol rate offset (top-level)
|
| 282 | - ``DPLL_FFO_PIN_DEVICE`` - pin vs parent DPLL offset (per-parent)
|
| 283 |
|
| 284 | The driver declares which types it supports via the ``supported_ffo``
|
| 285 | bitmask in ``struct dpll_pin_ops``. The core only calls the ``ffo_get``
|
| 286 | callback for types the driver has opted into. The requested type is
|
| 287 | passed to the driver in the ``struct dpll_ffo_param``.
|
| 288 |
|
| 289 | Frequency monitor
|
| 290 | =================
|
| 291 |
|
| 292 | Some DPLL devices may offer the capability to measure the actual
|
| 293 | frequency of all available input pins. The attribute and current feature state
|
| 294 | shall be included in the response message of the ``DPLL_CMD_DEVICE_GET``
|
| 295 | command for supported DPLL devices. In such cases, users can also control
|
| 296 | the feature using the ``DPLL_CMD_DEVICE_SET`` command by setting the
|
| 297 | ``enum dpll_feature_state`` values for the attribute.
|
| 298 | Once enabled the measured input frequency for each input pin shall be
|
| 299 | returned in the ``DPLL_A_PIN_MEASURED_FREQUENCY`` attribute. The value
|
| 300 | is in millihertz (mHz), using ``DPLL_PIN_MEASURED_FREQUENCY_DIVIDER``
|
| 301 | as the divider.
|
| 302 |
|
| 303 | =============================== ========================
|
| 304 | ``DPLL_A_FREQUENCY_MONITOR`` attr state of a feature
|
| 305 | =============================== ========================
|
| 306 |
|
| 307 | Embedded SYNC
|
| 308 | =============
|
| 309 |
|
| 310 | Device may provide ability to use Embedded SYNC feature. It allows
|
| 311 | to embed additional SYNC signal into the base frequency of a pin - a one
|
| 312 | special pulse of base frequency signal every time SYNC signal pulse
|
| 313 | happens. The user can configure the frequency of Embedded SYNC.
|
| 314 | The Embedded SYNC capability is always related to a given base frequency
|
| 315 | and HW capabilities. The user is provided a range of Embedded SYNC
|
| 316 | frequencies supported, depending on current base frequency configured for
|
| 317 | the pin.
|
| 318 |
|
| 319 | ========================================= =================================
|
| 320 | ``DPLL_A_PIN_ESYNC_FREQUENCY`` current Embedded SYNC frequency
|
| 321 | ``DPLL_A_PIN_ESYNC_FREQUENCY_SUPPORTED`` nest available Embedded SYNC
|
| 322 | frequency ranges
|
| 323 | ``DPLL_A_PIN_FREQUENCY_MIN`` attr minimum value of frequency
|
| 324 | ``DPLL_A_PIN_FREQUENCY_MAX`` attr maximum value of frequency
|
| 325 | ``DPLL_A_PIN_ESYNC_PULSE`` pulse type of Embedded SYNC
|
| 326 | ========================================= =================================
|
| 327 |
|
| 328 | Reference SYNC
|
| 329 | ==============
|
| 330 |
|
| 331 | The device may support the Reference SYNC feature, which allows the combination
|
| 332 | of two inputs into a input pair. In this configuration, clock signals
|
| 333 | from both inputs are used to synchronize the DPLL device. The higher frequency
|
| 334 | signal is utilized for the loop bandwidth of the DPLL, while the lower frequency
|
| 335 | signal is used to syntonize the output signal of the DPLL device. This feature
|
| 336 | enables the provision of a high-quality loop bandwidth signal from an external
|
| 337 | source.
|
| 338 |
|
| 339 | A capable input provides a list of inputs that can be bound with to create
|
| 340 | Reference SYNC. To control this feature, the user must request a desired
|
| 341 | state for a target pin: use ``DPLL_PIN_STATE_CONNECTED`` to enable or
|
| 342 | ``DPLL_PIN_STATE_DISCONNECTED`` to disable the feature. An input pin can be
|
| 343 | bound to only one other pin at any given time.
|
| 344 |
|
| 345 | ============================== ==========================================
|
| 346 | ``DPLL_A_PIN_REFERENCE_SYNC`` nested attribute for providing info or
|
| 347 | requesting configuration of the Reference
|
| 348 | SYNC feature
|
| 349 | ``DPLL_A_PIN_ID`` target pin id for Reference SYNC feature
|
| 350 | ``DPLL_A_PIN_STATE`` state of Reference SYNC connection
|
| 351 | ============================== ==========================================
|
| 352 |
|
| 353 | Configuration commands group
|
| 354 | ============================
|
| 355 |
|
| 356 | Configuration commands are used to get information about registered
|
| 357 | dpll devices (and pins), as well as set configuration of device or pins.
|
| 358 | As dpll devices must be abstracted and reflect real hardware,
|
| 359 | there is no way to add new dpll device via netlink from user space and
|
| 360 | each device should be registered by its driver.
|
| 361 |
|
| 362 | All netlink commands require ``GENL_ADMIN_PERM``. This is to prevent
|
| 363 | any spamming/DoS from unauthorized userspace applications.
|
| 364 |
|
| 365 | List of netlink commands with possible attributes
|
| 366 | =================================================
|
| 367 |
|
| 368 | Constants identifying command types for dpll device uses a
|
| 369 | ``DPLL_CMD_`` prefix and suffix according to command purpose.
|
| 370 | The dpll device related attributes use a ``DPLL_A_`` prefix and
|
| 371 | suffix according to attribute purpose.
|
| 372 |
|
| 373 | ==================================== =================================
|
| 374 | ``DPLL_CMD_DEVICE_ID_GET`` command to get device ID
|
| 375 | ``DPLL_A_MODULE_NAME`` attr module name of registerer
|
| 376 | ``DPLL_A_CLOCK_ID`` attr Unique Clock Identifier
|
| 377 | (EUI-64), as defined by the
|
| 378 | IEEE 1588 standard
|
| 379 | ``DPLL_A_TYPE`` attr type of dpll device
|
| 380 | ==================================== =================================
|
| 381 |
|
| 382 | ==================================== =================================
|
| 383 | ``DPLL_CMD_DEVICE_GET`` command to get device info or
|
| 384 | dump list of available devices
|
| 385 | ``DPLL_A_ID`` attr unique dpll device ID
|
| 386 | ``DPLL_A_MODULE_NAME`` attr module name of registerer
|
| 387 | ``DPLL_A_CLOCK_ID`` attr Unique Clock Identifier
|
| 388 | (EUI-64), as defined by the
|
| 389 | IEEE 1588 standard
|
| 390 | ``DPLL_A_MODE`` attr selection mode
|
| 391 | ``DPLL_A_MODE_SUPPORTED`` attr available selection modes
|
| 392 | ``DPLL_A_LOCK_STATUS`` attr dpll device lock status
|
| 393 | ``DPLL_A_TEMP`` attr device temperature info
|
| 394 | ``DPLL_A_TYPE`` attr type of dpll device
|
| 395 | ==================================== =================================
|
| 396 |
|
| 397 | ==================================== =================================
|
| 398 | ``DPLL_CMD_DEVICE_SET`` command to set dpll device config
|
| 399 | ``DPLL_A_ID`` attr internal dpll device index
|
| 400 | ``DPLL_A_MODE`` attr selection mode to configure
|
| 401 | ==================================== =================================
|
| 402 |
|
| 403 | Constants identifying command types for pins uses a
|
| 404 | ``DPLL_CMD_PIN_`` prefix and suffix according to command purpose.
|
| 405 | The pin related attributes use a ``DPLL_A_PIN_`` prefix and suffix
|
| 406 | according to attribute purpose.
|
| 407 |
|
| 408 | ==================================== =================================
|
| 409 | ``DPLL_CMD_PIN_ID_GET`` command to get pin ID
|
| 410 | ``DPLL_A_PIN_MODULE_NAME`` attr module name of registerer
|
| 411 | ``DPLL_A_PIN_CLOCK_ID`` attr Unique Clock Identifier
|
| 412 | (EUI-64), as defined by the
|
| 413 | IEEE 1588 standard
|
| 414 | ``DPLL_A_PIN_BOARD_LABEL`` attr pin board label provided
|
| 415 | by registerer
|
| 416 | ``DPLL_A_PIN_PANEL_LABEL`` attr pin panel label provided
|
| 417 | by registerer
|
| 418 | ``DPLL_A_PIN_PACKAGE_LABEL`` attr pin package label provided
|
| 419 | by registerer
|
| 420 | ``DPLL_A_PIN_TYPE`` attr type of a pin
|
| 421 | ==================================== =================================
|
| 422 |
|
| 423 | ==================================== ==================================
|
| 424 | ``DPLL_CMD_PIN_GET`` command to get pin info or dump
|
| 425 | list of available pins
|
| 426 | ``DPLL_A_PIN_ID`` attr unique a pin ID
|
| 427 | ``DPLL_A_PIN_MODULE_NAME`` attr module name of registerer
|
| 428 | ``DPLL_A_PIN_CLOCK_ID`` attr Unique Clock Identifier
|
| 429 | (EUI-64), as defined by the
|
| 430 | IEEE 1588 standard
|
| 431 | ``DPLL_A_PIN_BOARD_LABEL`` attr pin board label provided
|
| 432 | by registerer
|
| 433 | ``DPLL_A_PIN_PANEL_LABEL`` attr pin panel label provided
|
| 434 | by registerer
|
| 435 | ``DPLL_A_PIN_PACKAGE_LABEL`` attr pin package label provided
|
| 436 | by registerer
|
| 437 | ``DPLL_A_PIN_TYPE`` attr type of a pin
|
| 438 | ``DPLL_A_PIN_FREQUENCY`` attr current frequency of a pin
|
| 439 | ``DPLL_A_PIN_FREQUENCY_SUPPORTED`` nested attr provides supported
|
| 440 | frequencies
|
| 441 | ``DPLL_A_PIN_ANY_FREQUENCY_MIN`` attr minimum value of frequency
|
| 442 | ``DPLL_A_PIN_ANY_FREQUENCY_MAX`` attr maximum value of frequency
|
| 443 | ``DPLL_A_PIN_PHASE_ADJUST_GRAN`` attr granularity of phase
|
| 444 | adjustment value
|
| 445 | ``DPLL_A_PIN_PHASE_ADJUST_MIN`` attr minimum value of phase
|
| 446 | adjustment
|
| 447 | ``DPLL_A_PIN_PHASE_ADJUST_MAX`` attr maximum value of phase
|
| 448 | adjustment
|
| 449 | ``DPLL_A_PIN_PHASE_ADJUST`` attr configured value of phase
|
| 450 | adjustment on parent device
|
| 451 | ``DPLL_A_PIN_PARENT_DEVICE`` nested attr for each parent device
|
| 452 | the pin is connected with
|
| 453 | ``DPLL_A_PIN_PARENT_ID`` attr parent dpll device id
|
| 454 | ``DPLL_A_PIN_PRIO`` attr priority of pin on the
|
| 455 | dpll device
|
| 456 | ``DPLL_A_PIN_STATE`` attr state of pin on the parent
|
| 457 | dpll device
|
| 458 | ``DPLL_A_PIN_DIRECTION`` attr direction of a pin on the
|
| 459 | parent dpll device
|
| 460 | ``DPLL_A_PIN_PHASE_OFFSET`` attr measured phase difference
|
| 461 | between a pin and parent dpll
|
| 462 | ``DPLL_A_PIN_PARENT_PIN`` nested attr for each parent pin
|
| 463 | the pin is connected with
|
| 464 | ``DPLL_A_PIN_PARENT_ID`` attr parent pin id
|
| 465 | ``DPLL_A_PIN_STATE`` attr state of pin on the parent
|
| 466 | pin
|
| 467 | ``DPLL_A_PIN_CAPABILITIES`` attr bitmask of pin capabilities
|
| 468 | ``DPLL_A_PIN_MEASURED_FREQUENCY`` attr measured frequency of
|
| 469 | an input pin in mHz
|
| 470 | ==================================== ==================================
|
| 471 |
|
| 472 | ==================================== =================================
|
| 473 | ``DPLL_CMD_PIN_SET`` command to set pins configuration
|
| 474 | ``DPLL_A_PIN_ID`` attr unique a pin ID
|
| 475 | ``DPLL_A_PIN_FREQUENCY`` attr requested frequency of a pin
|
| 476 | ``DPLL_A_PIN_PHASE_ADJUST`` attr requested value of phase
|
| 477 | adjustment on parent device
|
| 478 | ``DPLL_A_PIN_PARENT_DEVICE`` nested attr for each parent dpll
|
| 479 | device configuration request
|
| 480 | ``DPLL_A_PIN_PARENT_ID`` attr parent dpll device id
|
| 481 | ``DPLL_A_PIN_DIRECTION`` attr requested direction of a pin
|
| 482 | ``DPLL_A_PIN_PRIO`` attr requested priority of pin on
|
| 483 | the dpll device
|
| 484 | ``DPLL_A_PIN_STATE`` attr requested state of pin on
|
| 485 | the dpll device
|
| 486 | ``DPLL_A_PIN_PARENT_PIN`` nested attr for each parent pin
|
| 487 | configuration request
|
| 488 | ``DPLL_A_PIN_PARENT_ID`` attr parent pin id
|
| 489 | ``DPLL_A_PIN_STATE`` attr requested state of pin on
|
| 490 | parent pin
|
| 491 | ==================================== =================================
|
| 492 |
|
| 493 | Netlink dump requests
|
| 494 | =====================
|
| 495 |
|
| 496 | The ``DPLL_CMD_DEVICE_GET`` and ``DPLL_CMD_PIN_GET`` commands are
|
| 497 | capable of dump type netlink requests, in which case the response is in
|
| 498 | the same format as for their ``do`` request, but every device or pin
|
| 499 | registered in the system is returned.
|
| 500 |
|
| 501 | SET commands format
|
| 502 | ===================
|
| 503 |
|
| 504 | ``DPLL_CMD_DEVICE_SET`` - to target a dpll device, the user provides
|
| 505 | ``DPLL_A_ID``, which is unique identifier of dpll device in the system,
|
| 506 | as well as parameter being configured (``DPLL_A_MODE``).
|
| 507 |
|
| 508 | ``DPLL_CMD_PIN_SET`` - to target a pin user must provide a
|
| 509 | ``DPLL_A_PIN_ID``, which is unique identifier of a pin in the system.
|
| 510 | Also configured pin parameters must be added.
|
| 511 | If ``DPLL_A_PIN_FREQUENCY`` is configured, it is a property of the pin
|
| 512 | itself and applies to all dpll devices the pin is registered with, so the
|
| 513 | frequency attribute shall not be enclosed in ``DPLL_A_PIN_PARENT_DEVICE``.
|
| 514 | Other attributes: ``DPLL_A_PIN_PRIO``, ``DPLL_A_PIN_STATE`` or
|
| 515 | ``DPLL_A_PIN_DIRECTION`` must be enclosed in
|
| 516 | ``DPLL_A_PIN_PARENT_DEVICE`` as their configuration relates to only one
|
| 517 | of parent dplls, targeted by ``DPLL_A_PIN_PARENT_ID`` attribute which is
|
| 518 | also required inside that nest.
|
| 519 | For MUX-type pins the ``DPLL_A_PIN_STATE`` attribute is configured in
|
| 520 | similar way, by enclosing required state in ``DPLL_A_PIN_PARENT_PIN``
|
| 521 | nested attribute and targeted parent pin id in ``DPLL_A_PIN_PARENT_ID``.
|
| 522 |
|
| 523 | In general, it is possible to configure multiple parameters at once, but
|
| 524 | internally each parameter change will be invoked separately, where order
|
| 525 | of configuration is not guaranteed by any means.
|
| 526 |
|
| 527 | Configuration pre-defined enums
|
| 528 | ===============================
|
| 529 |
|
| 530 | .. kernel-doc:: include/uapi/linux/dpll.h
|
| 531 |
|
| 532 | Notifications
|
| 533 | =============
|
| 534 |
|
| 535 | dpll device can provide notifications regarding status changes of the
|
| 536 | device, i.e. lock status changes, input/output changes or other alarms.
|
| 537 | There is one multicast group that is used to notify user-space apps via
|
| 538 | netlink socket: ``DPLL_MCGRP_MONITOR``
|
| 539 |
|
| 540 | Notifications messages:
|
| 541 |
|
| 542 | ============================== =====================================
|
| 543 | ``DPLL_CMD_DEVICE_CREATE_NTF`` dpll device was created
|
| 544 | ``DPLL_CMD_DEVICE_DELETE_NTF`` dpll device was deleted
|
| 545 | ``DPLL_CMD_DEVICE_CHANGE_NTF`` dpll device has changed
|
| 546 | ``DPLL_CMD_PIN_CREATE_NTF`` dpll pin was created
|
| 547 | ``DPLL_CMD_PIN_DELETE_NTF`` dpll pin was deleted
|
| 548 | ``DPLL_CMD_PIN_CHANGE_NTF`` dpll pin has changed
|
| 549 | ============================== =====================================
|
| 550 |
|
| 551 | Events format is the same as for the corresponding get command.
|
| 552 | Format of ``DPLL_CMD_DEVICE_`` events is the same as response of
|
| 553 | ``DPLL_CMD_DEVICE_GET``.
|
| 554 | Format of ``DPLL_CMD_PIN_`` events is same as response of
|
| 555 | ``DPLL_CMD_PIN_GET``.
|
| 556 |
|
| 557 | Device driver implementation
|
| 558 | ============================
|
| 559 |
|
| 560 | Device is allocated by dpll_device_get() call. Second call with the
|
| 561 | same arguments will not create new object but provides pointer to
|
| 562 | previously created device for given arguments, it also increases
|
| 563 | refcount of that object.
|
| 564 | Device is deallocated by dpll_device_put() call, which first
|
| 565 | decreases the refcount, once refcount is cleared the object is
|
| 566 | destroyed.
|
| 567 |
|
| 568 | Device should implement set of operations and register device via
|
| 569 | dpll_device_register() at which point it becomes available to the
|
| 570 | users. Multiple driver instances can obtain reference to it with
|
| 571 | dpll_device_get(), as well as register dpll device with their own
|
| 572 | ops and priv.
|
| 573 |
|
| 574 | The pins are allocated separately with dpll_pin_get(), it works
|
| 575 | similarly to dpll_device_get(). Function first creates object and then
|
| 576 | for each call with the same arguments only the object refcount
|
| 577 | increases. Also dpll_pin_put() works similarly to dpll_device_put().
|
| 578 |
|
| 579 | A pin can be registered with parent dpll device or parent pin, depending
|
| 580 | on hardware needs. Each registration requires registerer to provide set
|
| 581 | of pin callbacks, and private data pointer for calling them:
|
| 582 |
|
| 583 | - dpll_pin_register() - register pin with a dpll device,
|
| 584 | - dpll_pin_on_pin_register() - register pin with another MUX type pin.
|
| 585 |
|
| 586 | Notifications of adding or removing dpll devices are created within
|
| 587 | subsystem itself.
|
| 588 | Notifications about registering/deregistering pins are also invoked by
|
| 589 | the subsystem.
|
| 590 | Notifications about status changes either of dpll device or a pin are
|
| 591 | invoked in two ways:
|
| 592 |
|
| 593 | - after successful change was requested on dpll subsystem, the subsystem
|
| 594 | calls corresponding notification,
|
| 595 | - requested by device driver with dpll_device_change_ntf() or
|
| 596 | dpll_pin_change_ntf() when driver informs about the status change.
|
| 597 |
|
| 598 | The device driver using dpll interface is not required to implement all
|
| 599 | the callback operation. Nevertheless, there are few required to be
|
| 600 | implemented.
|
| 601 | Required dpll device level callback operations:
|
| 602 |
|
| 603 | - ``.mode_get``,
|
| 604 | - ``.lock_status_get``.
|
| 605 |
|
| 606 | Required pin level callback operations:
|
| 607 |
|
| 608 | - ``.state_on_dpll_get`` (pins registered with dpll device),
|
| 609 | - ``.state_on_pin_get`` (pins registered with parent pin),
|
| 610 | - ``.direction_get``.
|
| 611 |
|
| 612 | Every other operation handler is checked for existence and
|
| 613 | ``-EOPNOTSUPP`` is returned in case of absence of specific handler.
|
| 614 |
|
| 615 | The simplest implementation is in the OCP TimeCard driver. The ops
|
| 616 | structures are defined like this:
|
| 617 |
|
| 618 | .. code-block:: c
|
| 619 |
|
| 620 | static const struct dpll_device_ops dpll_ops = {
|
| 621 | .lock_status_get = ptp_ocp_dpll_lock_status_get,
|
| 622 | .mode_get = ptp_ocp_dpll_mode_get,
|
| 623 | .mode_supported = ptp_ocp_dpll_mode_supported,
|
| 624 | };
|
| 625 |
|
| 626 | static const struct dpll_pin_ops dpll_pins_ops = {
|
| 627 | .frequency_get = ptp_ocp_dpll_frequency_get,
|
| 628 | .frequency_set = ptp_ocp_dpll_frequency_set,
|
| 629 | .direction_get = ptp_ocp_dpll_direction_get,
|
| 630 | .direction_set = ptp_ocp_dpll_direction_set,
|
| 631 | .state_on_dpll_get = ptp_ocp_dpll_state_get,
|
| 632 | };
|
| 633 |
|
| 634 | The registration part is then looks like this part:
|
| 635 |
|
| 636 | .. code-block:: c
|
| 637 |
|
| 638 | clkid = pci_get_dsn(pdev);
|
| 639 | bp->dpll = dpll_device_get(clkid, 0, THIS_MODULE);
|
| 640 | if (IS_ERR(bp->dpll)) {
|
| 641 | err = PTR_ERR(bp->dpll);
|
| 642 | dev_err(&pdev->dev, "dpll_device_alloc failed\n");
|
| 643 | goto out;
|
| 644 | }
|
| 645 |
|
| 646 | err = dpll_device_register(bp->dpll, DPLL_TYPE_PPS, &dpll_ops, bp);
|
| 647 | if (err)
|
| 648 | goto out;
|
| 649 |
|
| 650 | for (i = 0; i < OCP_SMA_NUM; i++) {
|
| 651 | bp->sma[i].dpll_pin = dpll_pin_get(clkid, i, THIS_MODULE, &bp->sma[i].dpll_prop);
|
| 652 | if (IS_ERR(bp->sma[i].dpll_pin)) {
|
| 653 | err = PTR_ERR(bp->dpll);
|
| 654 | goto out_dpll;
|
| 655 | }
|
| 656 |
|
| 657 | err = dpll_pin_register(bp->dpll, bp->sma[i].dpll_pin, &dpll_pins_ops,
|
| 658 | &bp->sma[i]);
|
| 659 | if (err) {
|
| 660 | dpll_pin_put(bp->sma[i].dpll_pin);
|
| 661 | goto out_dpll;
|
| 662 | }
|
| 663 | }
|
| 664 |
|
| 665 | In the error path we have to rewind every allocation in the reverse order:
|
| 666 |
|
| 667 | .. code-block:: c
|
| 668 |
|
| 669 | while (i) {
|
| 670 | --i;
|
| 671 | dpll_pin_unregister(bp->dpll, bp->sma[i].dpll_pin, &dpll_pins_ops, &bp->sma[i]);
|
| 672 | dpll_pin_put(bp->sma[i].dpll_pin);
|
| 673 | }
|
| 674 | dpll_device_put(bp->dpll);
|
| 675 |
|
| 676 | More complex example can be found in Intel's ICE driver or nVidia's mlx5 driver.
|
| 677 |
|
| 678 | SyncE enablement
|
| 679 | ================
|
| 680 | For SyncE enablement it is required to allow control over dpll device
|
| 681 | for a software application which monitors and configures the inputs of
|
| 682 | dpll device in response to current state of a dpll device and its
|
| 683 | inputs.
|
| 684 | In such scenario, dpll device input signal shall be also configurable
|
| 685 | to drive dpll with signal recovered from the PHY netdevice.
|
| 686 | This is done by exposing a pin to the netdevice - attaching pin to the
|
| 687 | netdevice itself with
|
| 688 | ``dpll_netdev_pin_set(struct net_device *dev, struct dpll_pin *dpll_pin)``.
|
| 689 | Exposed pin id handle ``DPLL_A_PIN_ID`` is then identifiable by the user
|
| 690 | as it is attached to rtnetlink respond to get ``RTM_NEWLINK`` command in
|
| 691 | nested attribute ``IFLA_DPLL_PIN``.
|