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

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'add-microchip-zl3073x-support-part-1'

Ivan Vecera says:

====================
Add Microchip ZL3073x support (part 1)

Add support for Microchip Azurite DPLL/PTP/SyncE chip family that
provides DPLL and PTP functionality. This series bring first part
that adds the core functionality and basic DPLL support.

The next part of the series will bring additional DPLL functionality
like eSync support, phase offset and frequency offset reporting and
phase adjustments.

Testing was done by myself and by Prathosh Satish on Microchip EDS2
development board with ZL30732 DPLL chip connected over I2C bus.
====================

Link: https://patch.msgid.link/20250704182202.1641943-1-ivecera@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+4175 -2
+76
Documentation/devicetree/bindings/dpll/dpll-device.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/dpll/dpll-device.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Digital Phase-Locked Loop (DPLL) Device 8 + 9 + maintainers: 10 + - Ivan Vecera <ivecera@redhat.com> 11 + 12 + description: 13 + Digital Phase-Locked Loop (DPLL) device is used for precise clock 14 + synchronization in networking and telecom hardware. The device can 15 + have one or more channels (DPLLs) and one or more physical input and 16 + output pins. Each DPLL channel can either produce pulse-per-clock signal 17 + or drive ethernet equipment clock. The type of each channel can be 18 + indicated by dpll-types property. 19 + 20 + properties: 21 + $nodename: 22 + pattern: "^dpll(@.*)?$" 23 + 24 + "#address-cells": 25 + const: 0 26 + 27 + "#size-cells": 28 + const: 0 29 + 30 + dpll-types: 31 + description: List of DPLL channel types, one per DPLL instance. 32 + $ref: /schemas/types.yaml#/definitions/non-unique-string-array 33 + items: 34 + enum: [pps, eec] 35 + 36 + input-pins: 37 + type: object 38 + description: DPLL input pins 39 + unevaluatedProperties: false 40 + 41 + properties: 42 + "#address-cells": 43 + const: 1 44 + "#size-cells": 45 + const: 0 46 + 47 + patternProperties: 48 + "^pin@[0-9a-f]+$": 49 + $ref: /schemas/dpll/dpll-pin.yaml 50 + unevaluatedProperties: false 51 + 52 + required: 53 + - "#address-cells" 54 + - "#size-cells" 55 + 56 + output-pins: 57 + type: object 58 + description: DPLL output pins 59 + unevaluatedProperties: false 60 + 61 + properties: 62 + "#address-cells": 63 + const: 1 64 + "#size-cells": 65 + const: 0 66 + 67 + patternProperties: 68 + "^pin@[0-9]+$": 69 + $ref: /schemas/dpll/dpll-pin.yaml 70 + unevaluatedProperties: false 71 + 72 + required: 73 + - "#address-cells" 74 + - "#size-cells" 75 + 76 + additionalProperties: true
+45
Documentation/devicetree/bindings/dpll/dpll-pin.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/dpll/dpll-pin.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: DPLL Pin 8 + 9 + maintainers: 10 + - Ivan Vecera <ivecera@redhat.com> 11 + 12 + description: | 13 + The DPLL pin is either a physical input or output pin that is provided 14 + by a DPLL( Digital Phase-Locked Loop) device. The pin is identified by 15 + its physical order number that is stored in reg property and can have 16 + an additional set of properties like supported (allowed) frequencies, 17 + label, type and may support embedded sync. 18 + 19 + Note that the pin in this context has nothing to do with pinctrl. 20 + 21 + properties: 22 + reg: 23 + description: Hardware index of the DPLL pin. 24 + maxItems: 1 25 + 26 + connection-type: 27 + description: Connection type of the pin 28 + $ref: /schemas/types.yaml#/definitions/string 29 + enum: [ext, gnss, int, mux, synce] 30 + 31 + esync-control: 32 + description: Indicates whether the pin supports embedded sync functionality. 33 + type: boolean 34 + 35 + label: 36 + description: String exposed as the pin board label 37 + $ref: /schemas/types.yaml#/definitions/string 38 + 39 + supported-frequencies-hz: 40 + description: List of supported frequencies for this pin, expressed in Hz. 41 + 42 + required: 43 + - reg 44 + 45 + additionalProperties: false
+115
Documentation/devicetree/bindings/dpll/microchip,zl30731.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/dpll/microchip,zl30731.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Microchip Azurite DPLL device 8 + 9 + maintainers: 10 + - Ivan Vecera <ivecera@redhat.com> 11 + 12 + description: 13 + Microchip Azurite DPLL (ZL3073x) is a family of DPLL devices that 14 + provides up to 5 independent DPLL channels, up to 10 differential or 15 + single-ended inputs and 10 differential or 20 single-ended outputs. 16 + These devices support both I2C and SPI interfaces. 17 + 18 + properties: 19 + compatible: 20 + enum: 21 + - microchip,zl30731 22 + - microchip,zl30732 23 + - microchip,zl30733 24 + - microchip,zl30734 25 + - microchip,zl30735 26 + 27 + reg: 28 + maxItems: 1 29 + 30 + required: 31 + - compatible 32 + - reg 33 + 34 + allOf: 35 + - $ref: /schemas/dpll/dpll-device.yaml# 36 + - $ref: /schemas/spi/spi-peripheral-props.yaml# 37 + 38 + unevaluatedProperties: false 39 + 40 + examples: 41 + - | 42 + i2c { 43 + #address-cells = <1>; 44 + #size-cells = <0>; 45 + 46 + dpll@70 { 47 + compatible = "microchip,zl30732"; 48 + reg = <0x70>; 49 + dpll-types = "pps", "eec"; 50 + 51 + input-pins { 52 + #address-cells = <1>; 53 + #size-cells = <0>; 54 + 55 + pin@0 { /* REF0P */ 56 + reg = <0>; 57 + connection-type = "ext"; 58 + label = "Input 0"; 59 + supported-frequencies-hz = /bits/ 64 <1 1000>; 60 + }; 61 + }; 62 + 63 + output-pins { 64 + #address-cells = <1>; 65 + #size-cells = <0>; 66 + 67 + pin@3 { /* OUT1N */ 68 + reg = <3>; 69 + connection-type = "gnss"; 70 + esync-control; 71 + label = "Output 1"; 72 + supported-frequencies-hz = /bits/ 64 <1 10000>; 73 + }; 74 + }; 75 + }; 76 + }; 77 + - | 78 + spi { 79 + #address-cells = <1>; 80 + #size-cells = <0>; 81 + 82 + dpll@70 { 83 + compatible = "microchip,zl30731"; 84 + reg = <0x70>; 85 + spi-max-frequency = <12500000>; 86 + 87 + dpll-types = "pps"; 88 + 89 + input-pins { 90 + #address-cells = <1>; 91 + #size-cells = <0>; 92 + 93 + pin@0 { /* REF0P */ 94 + reg = <0>; 95 + connection-type = "ext"; 96 + label = "Input 0"; 97 + supported-frequencies-hz = /bits/ 64 <1 1000>; 98 + }; 99 + }; 100 + 101 + output-pins { 102 + #address-cells = <1>; 103 + #size-cells = <0>; 104 + 105 + pin@3 { /* OUT1N */ 106 + reg = <3>; 107 + connection-type = "gnss"; 108 + esync-control; 109 + label = "Output 1"; 110 + supported-frequencies-hz = /bits/ 64 <1 10000>; 111 + }; 112 + }; 113 + }; 114 + }; 115 + ...
+1
Documentation/networking/devlink/index.rst
··· 98 98 iosm 99 99 octeontx2 100 100 sfc 101 + zl3073x
+51
Documentation/networking/devlink/zl3073x.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + ======================= 4 + zl3073x devlink support 5 + ======================= 6 + 7 + This document describes the devlink features implemented by the ``zl3073x`` 8 + device driver. 9 + 10 + Parameters 11 + ========== 12 + 13 + .. list-table:: Generic parameters implemented 14 + :widths: 5 5 90 15 + 16 + * - Name 17 + - Mode 18 + - Notes 19 + * - ``clock_id`` 20 + - driverinit 21 + - Set the clock ID that is used by the driver for registering DPLL devices 22 + and pins. 23 + 24 + Info versions 25 + ============= 26 + 27 + The ``zl3073x`` driver reports the following versions 28 + 29 + .. list-table:: devlink info versions implemented 30 + :widths: 5 5 5 90 31 + 32 + * - Name 33 + - Type 34 + - Example 35 + - Description 36 + * - ``asic.id`` 37 + - fixed 38 + - 1E94 39 + - Chip identification number 40 + * - ``asic.rev`` 41 + - fixed 42 + - 300 43 + - Chip revision number 44 + * - ``fw`` 45 + - running 46 + - 7006 47 + - Firmware version number 48 + * - ``custom_cfg`` 49 + - running 50 + - 1.3.0.1 51 + - Device configuration version customized by OEM
+10
MAINTAINERS
··· 7335 7335 M: Jiri Pirko <jiri@resnulli.us> 7336 7336 L: netdev@vger.kernel.org 7337 7337 S: Supported 7338 + F: Documentation/devicetree/bindings/dpll/dpll-device.yaml 7339 + F: Documentation/devicetree/bindings/dpll/dpll-pin.yaml 7338 7340 F: Documentation/driver-api/dpll.rst 7339 7341 F: drivers/dpll/* 7340 7342 F: include/linux/dpll.h ··· 16513 16511 L: linux-wireless@vger.kernel.org 16514 16512 S: Supported 16515 16513 F: drivers/net/wireless/microchip/ 16514 + 16515 + MICROCHIP ZL3073X DRIVER 16516 + M: Ivan Vecera <ivecera@redhat.com> 16517 + M: Prathosh Satish <Prathosh.Satish@microchip.com> 16518 + L: netdev@vger.kernel.org 16519 + S: Supported 16520 + F: Documentation/devicetree/bindings/dpll/microchip,zl30731.yaml 16521 + F: drivers/dpll/zl3073x/ 16516 16522 16517 16523 MICROSEMI MIPS SOCS 16518 16524 M: Alexandre Belloni <alexandre.belloni@bootlin.com>
+2 -2
drivers/Kconfig
··· 77 77 78 78 source "drivers/ptp/Kconfig" 79 79 80 + source "drivers/dpll/Kconfig" 81 + 80 82 source "drivers/pinctrl/Kconfig" 81 83 82 84 source "drivers/gpio/Kconfig" ··· 246 244 source "drivers/hte/Kconfig" 247 245 248 246 source "drivers/cdx/Kconfig" 249 - 250 - source "drivers/dpll/Kconfig" 251 247 252 248 endmenu
+6
drivers/dpll/Kconfig
··· 3 3 # Generic DPLL drivers configuration 4 4 # 5 5 6 + menu "DPLL device support" 7 + 6 8 config DPLL 7 9 bool 10 + 11 + source "drivers/dpll/zl3073x/Kconfig" 12 + 13 + endmenu
+2
drivers/dpll/Makefile
··· 7 7 dpll-y += dpll_core.o 8 8 dpll-y += dpll_netlink.o 9 9 dpll-y += dpll_nl.o 10 + 11 + obj-$(CONFIG_ZL3073X) += zl3073x/
+38
drivers/dpll/zl3073x/Kconfig
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + 3 + config ZL3073X 4 + tristate "Microchip Azurite DPLL/PTP/SyncE devices" 5 + depends on NET 6 + select DPLL 7 + select NET_DEVLINK 8 + help 9 + This driver supports Microchip Azurite family DPLL/PTP/SyncE 10 + devices that support up to 5 independent DPLL channels, 11 + 10 input pins and up to 20 output pins. 12 + 13 + To compile this driver as a module, choose M here. The module 14 + will be called zl3073x. 15 + 16 + config ZL3073X_I2C 17 + tristate "I2C bus implementation for Microchip Azurite devices" 18 + depends on I2C && ZL3073X 19 + select REGMAP_I2C 20 + default m 21 + help 22 + This is I2C bus implementation for Microchip Azurite DPLL/PTP/SyncE 23 + devices. 24 + 25 + To compile this driver as a module, choose M here: the module will 26 + be called zl3073x_i2c. 27 + 28 + config ZL3073X_SPI 29 + tristate "SPI bus implementation for Microchip Azurite devices" 30 + depends on SPI && ZL3073X 31 + select REGMAP_SPI 32 + default m 33 + help 34 + This is SPI bus implementation for Microchip Azurite DPLL/PTP/SyncE 35 + devices. 36 + 37 + To compile this driver as a module, choose M here: the module will 38 + be called zl3073x_spi.
+10
drivers/dpll/zl3073x/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + 3 + obj-$(CONFIG_ZL3073X) += zl3073x.o 4 + zl3073x-objs := core.o devlink.o dpll.o prop.o 5 + 6 + obj-$(CONFIG_ZL3073X_I2C) += zl3073x_i2c.o 7 + zl3073x_i2c-objs := i2c.o 8 + 9 + obj-$(CONFIG_ZL3073X_SPI) += zl3073x_spi.o 10 + zl3073x_spi-objs := spi.o
+859
drivers/dpll/zl3073x/core.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + 3 + #include <linux/array_size.h> 4 + #include <linux/bitfield.h> 5 + #include <linux/bits.h> 6 + #include <linux/dev_printk.h> 7 + #include <linux/device.h> 8 + #include <linux/export.h> 9 + #include <linux/math64.h> 10 + #include <linux/module.h> 11 + #include <linux/netlink.h> 12 + #include <linux/regmap.h> 13 + #include <linux/sprintf.h> 14 + #include <linux/string_choices.h> 15 + #include <linux/unaligned.h> 16 + #include <net/devlink.h> 17 + 18 + #include "core.h" 19 + #include "devlink.h" 20 + #include "dpll.h" 21 + #include "regs.h" 22 + 23 + /* Chip IDs for zl30731 */ 24 + static const u16 zl30731_ids[] = { 25 + 0x0E93, 26 + 0x1E93, 27 + 0x2E93, 28 + }; 29 + 30 + const struct zl3073x_chip_info zl30731_chip_info = { 31 + .ids = zl30731_ids, 32 + .num_ids = ARRAY_SIZE(zl30731_ids), 33 + .num_channels = 1, 34 + }; 35 + EXPORT_SYMBOL_NS_GPL(zl30731_chip_info, "ZL3073X"); 36 + 37 + /* Chip IDs for zl30732 */ 38 + static const u16 zl30732_ids[] = { 39 + 0x0E30, 40 + 0x0E94, 41 + 0x1E94, 42 + 0x1F60, 43 + 0x2E94, 44 + 0x3FC4, 45 + }; 46 + 47 + const struct zl3073x_chip_info zl30732_chip_info = { 48 + .ids = zl30732_ids, 49 + .num_ids = ARRAY_SIZE(zl30732_ids), 50 + .num_channels = 2, 51 + }; 52 + EXPORT_SYMBOL_NS_GPL(zl30732_chip_info, "ZL3073X"); 53 + 54 + /* Chip IDs for zl30733 */ 55 + static const u16 zl30733_ids[] = { 56 + 0x0E95, 57 + 0x1E95, 58 + 0x2E95, 59 + }; 60 + 61 + const struct zl3073x_chip_info zl30733_chip_info = { 62 + .ids = zl30733_ids, 63 + .num_ids = ARRAY_SIZE(zl30733_ids), 64 + .num_channels = 3, 65 + }; 66 + EXPORT_SYMBOL_NS_GPL(zl30733_chip_info, "ZL3073X"); 67 + 68 + /* Chip IDs for zl30734 */ 69 + static const u16 zl30734_ids[] = { 70 + 0x0E96, 71 + 0x1E96, 72 + 0x2E96, 73 + }; 74 + 75 + const struct zl3073x_chip_info zl30734_chip_info = { 76 + .ids = zl30734_ids, 77 + .num_ids = ARRAY_SIZE(zl30734_ids), 78 + .num_channels = 4, 79 + }; 80 + EXPORT_SYMBOL_NS_GPL(zl30734_chip_info, "ZL3073X"); 81 + 82 + /* Chip IDs for zl30735 */ 83 + static const u16 zl30735_ids[] = { 84 + 0x0E97, 85 + 0x1E97, 86 + 0x2E97, 87 + }; 88 + 89 + const struct zl3073x_chip_info zl30735_chip_info = { 90 + .ids = zl30735_ids, 91 + .num_ids = ARRAY_SIZE(zl30735_ids), 92 + .num_channels = 5, 93 + }; 94 + EXPORT_SYMBOL_NS_GPL(zl30735_chip_info, "ZL3073X"); 95 + 96 + #define ZL_RANGE_OFFSET 0x80 97 + #define ZL_PAGE_SIZE 0x80 98 + #define ZL_NUM_PAGES 15 99 + #define ZL_PAGE_SEL 0x7F 100 + #define ZL_PAGE_SEL_MASK GENMASK(3, 0) 101 + #define ZL_NUM_REGS (ZL_NUM_PAGES * ZL_PAGE_SIZE) 102 + 103 + /* Regmap range configuration */ 104 + static const struct regmap_range_cfg zl3073x_regmap_range = { 105 + .range_min = ZL_RANGE_OFFSET, 106 + .range_max = ZL_RANGE_OFFSET + ZL_NUM_REGS - 1, 107 + .selector_reg = ZL_PAGE_SEL, 108 + .selector_mask = ZL_PAGE_SEL_MASK, 109 + .selector_shift = 0, 110 + .window_start = 0, 111 + .window_len = ZL_PAGE_SIZE, 112 + }; 113 + 114 + static bool 115 + zl3073x_is_volatile_reg(struct device *dev __maybe_unused, unsigned int reg) 116 + { 117 + /* Only page selector is non-volatile */ 118 + return reg != ZL_PAGE_SEL; 119 + } 120 + 121 + const struct regmap_config zl3073x_regmap_config = { 122 + .reg_bits = 8, 123 + .val_bits = 8, 124 + .max_register = ZL_RANGE_OFFSET + ZL_NUM_REGS - 1, 125 + .ranges = &zl3073x_regmap_range, 126 + .num_ranges = 1, 127 + .cache_type = REGCACHE_MAPLE, 128 + .volatile_reg = zl3073x_is_volatile_reg, 129 + }; 130 + EXPORT_SYMBOL_NS_GPL(zl3073x_regmap_config, "ZL3073X"); 131 + 132 + /** 133 + * zl3073x_ref_freq_factorize - factorize given frequency 134 + * @freq: input frequency 135 + * @base: base frequency 136 + * @mult: multiplier 137 + * 138 + * Checks if the given frequency can be factorized using one of the 139 + * supported base frequencies. If so the base frequency and multiplier 140 + * are stored into appropriate parameters if they are not NULL. 141 + * 142 + * Return: 0 on success, -EINVAL if the frequency cannot be factorized 143 + */ 144 + int 145 + zl3073x_ref_freq_factorize(u32 freq, u16 *base, u16 *mult) 146 + { 147 + static const u16 base_freqs[] = { 148 + 1, 2, 4, 5, 8, 10, 16, 20, 25, 32, 40, 50, 64, 80, 100, 125, 149 + 128, 160, 200, 250, 256, 320, 400, 500, 625, 640, 800, 1000, 150 + 1250, 1280, 1600, 2000, 2500, 3125, 3200, 4000, 5000, 6250, 151 + 6400, 8000, 10000, 12500, 15625, 16000, 20000, 25000, 31250, 152 + 32000, 40000, 50000, 62500, 153 + }; 154 + u32 div; 155 + int i; 156 + 157 + for (i = 0; i < ARRAY_SIZE(base_freqs); i++) { 158 + div = freq / base_freqs[i]; 159 + 160 + if (div <= U16_MAX && (freq % base_freqs[i]) == 0) { 161 + if (base) 162 + *base = base_freqs[i]; 163 + if (mult) 164 + *mult = div; 165 + 166 + return 0; 167 + } 168 + } 169 + 170 + return -EINVAL; 171 + } 172 + 173 + static bool 174 + zl3073x_check_reg(struct zl3073x_dev *zldev, unsigned int reg, size_t size) 175 + { 176 + /* Check that multiop lock is held when accessing registers 177 + * from page 10 and above. 178 + */ 179 + if (ZL_REG_PAGE(reg) >= 10) 180 + lockdep_assert_held(&zldev->multiop_lock); 181 + 182 + /* Check the index is in valid range for indexed register */ 183 + if (ZL_REG_OFFSET(reg) > ZL_REG_MAX_OFFSET(reg)) { 184 + dev_err(zldev->dev, "Index out of range for reg 0x%04lx\n", 185 + ZL_REG_ADDR(reg)); 186 + return false; 187 + } 188 + /* Check the requested size corresponds to register size */ 189 + if (ZL_REG_SIZE(reg) != size) { 190 + dev_err(zldev->dev, "Invalid size %zu for reg 0x%04lx\n", 191 + size, ZL_REG_ADDR(reg)); 192 + return false; 193 + } 194 + 195 + return true; 196 + } 197 + 198 + static int 199 + zl3073x_read_reg(struct zl3073x_dev *zldev, unsigned int reg, void *val, 200 + size_t size) 201 + { 202 + int rc; 203 + 204 + if (!zl3073x_check_reg(zldev, reg, size)) 205 + return -EINVAL; 206 + 207 + /* Map the register address to virtual range */ 208 + reg = ZL_REG_ADDR(reg) + ZL_RANGE_OFFSET; 209 + 210 + rc = regmap_bulk_read(zldev->regmap, reg, val, size); 211 + if (rc) { 212 + dev_err(zldev->dev, "Failed to read reg 0x%04x: %pe\n", reg, 213 + ERR_PTR(rc)); 214 + return rc; 215 + } 216 + 217 + return 0; 218 + } 219 + 220 + static int 221 + zl3073x_write_reg(struct zl3073x_dev *zldev, unsigned int reg, const void *val, 222 + size_t size) 223 + { 224 + int rc; 225 + 226 + if (!zl3073x_check_reg(zldev, reg, size)) 227 + return -EINVAL; 228 + 229 + /* Map the register address to virtual range */ 230 + reg = ZL_REG_ADDR(reg) + ZL_RANGE_OFFSET; 231 + 232 + rc = regmap_bulk_write(zldev->regmap, reg, val, size); 233 + if (rc) { 234 + dev_err(zldev->dev, "Failed to write reg 0x%04x: %pe\n", reg, 235 + ERR_PTR(rc)); 236 + return rc; 237 + } 238 + 239 + return 0; 240 + } 241 + 242 + /** 243 + * zl3073x_read_u8 - read value from 8bit register 244 + * @zldev: zl3073x device pointer 245 + * @reg: register to write to 246 + * @val: value to write 247 + * 248 + * Reads value from given 8bit register. 249 + * 250 + * Returns: 0 on success, <0 on error 251 + */ 252 + int zl3073x_read_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 *val) 253 + { 254 + return zl3073x_read_reg(zldev, reg, val, sizeof(*val)); 255 + } 256 + 257 + /** 258 + * zl3073x_write_u8 - write value to 16bit register 259 + * @zldev: zl3073x device pointer 260 + * @reg: register to write to 261 + * @val: value to write 262 + * 263 + * Writes value into given 8bit register. 264 + * 265 + * Returns: 0 on success, <0 on error 266 + */ 267 + int zl3073x_write_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 val) 268 + { 269 + return zl3073x_write_reg(zldev, reg, &val, sizeof(val)); 270 + } 271 + 272 + /** 273 + * zl3073x_read_u16 - read value from 16bit register 274 + * @zldev: zl3073x device pointer 275 + * @reg: register to write to 276 + * @val: value to write 277 + * 278 + * Reads value from given 16bit register. 279 + * 280 + * Returns: 0 on success, <0 on error 281 + */ 282 + int zl3073x_read_u16(struct zl3073x_dev *zldev, unsigned int reg, u16 *val) 283 + { 284 + int rc; 285 + 286 + rc = zl3073x_read_reg(zldev, reg, val, sizeof(*val)); 287 + if (!rc) 288 + be16_to_cpus(val); 289 + 290 + return rc; 291 + } 292 + 293 + /** 294 + * zl3073x_write_u16 - write value to 16bit register 295 + * @zldev: zl3073x device pointer 296 + * @reg: register to write to 297 + * @val: value to write 298 + * 299 + * Writes value into given 16bit register. 300 + * 301 + * Returns: 0 on success, <0 on error 302 + */ 303 + int zl3073x_write_u16(struct zl3073x_dev *zldev, unsigned int reg, u16 val) 304 + { 305 + cpu_to_be16s(&val); 306 + 307 + return zl3073x_write_reg(zldev, reg, &val, sizeof(val)); 308 + } 309 + 310 + /** 311 + * zl3073x_read_u32 - read value from 32bit register 312 + * @zldev: zl3073x device pointer 313 + * @reg: register to write to 314 + * @val: value to write 315 + * 316 + * Reads value from given 32bit register. 317 + * 318 + * Returns: 0 on success, <0 on error 319 + */ 320 + int zl3073x_read_u32(struct zl3073x_dev *zldev, unsigned int reg, u32 *val) 321 + { 322 + int rc; 323 + 324 + rc = zl3073x_read_reg(zldev, reg, val, sizeof(*val)); 325 + if (!rc) 326 + be32_to_cpus(val); 327 + 328 + return rc; 329 + } 330 + 331 + /** 332 + * zl3073x_write_u32 - write value to 32bit register 333 + * @zldev: zl3073x device pointer 334 + * @reg: register to write to 335 + * @val: value to write 336 + * 337 + * Writes value into given 32bit register. 338 + * 339 + * Returns: 0 on success, <0 on error 340 + */ 341 + int zl3073x_write_u32(struct zl3073x_dev *zldev, unsigned int reg, u32 val) 342 + { 343 + cpu_to_be32s(&val); 344 + 345 + return zl3073x_write_reg(zldev, reg, &val, sizeof(val)); 346 + } 347 + 348 + /** 349 + * zl3073x_read_u48 - read value from 48bit register 350 + * @zldev: zl3073x device pointer 351 + * @reg: register to write to 352 + * @val: value to write 353 + * 354 + * Reads value from given 48bit register. 355 + * 356 + * Returns: 0 on success, <0 on error 357 + */ 358 + int zl3073x_read_u48(struct zl3073x_dev *zldev, unsigned int reg, u64 *val) 359 + { 360 + u8 buf[6]; 361 + int rc; 362 + 363 + rc = zl3073x_read_reg(zldev, reg, buf, sizeof(buf)); 364 + if (!rc) 365 + *val = get_unaligned_be48(buf); 366 + 367 + return rc; 368 + } 369 + 370 + /** 371 + * zl3073x_write_u48 - write value to 48bit register 372 + * @zldev: zl3073x device pointer 373 + * @reg: register to write to 374 + * @val: value to write 375 + * 376 + * Writes value into given 48bit register. 377 + * The value must be from the interval -S48_MIN to U48_MAX. 378 + * 379 + * Returns: 0 on success, <0 on error 380 + */ 381 + int zl3073x_write_u48(struct zl3073x_dev *zldev, unsigned int reg, u64 val) 382 + { 383 + u8 buf[6]; 384 + 385 + /* Check the value belongs to <S48_MIN, U48_MAX> 386 + * Any value >= S48_MIN has bits 47..63 set. 387 + */ 388 + if (val > GENMASK_ULL(47, 0) && val < GENMASK_ULL(63, 47)) { 389 + dev_err(zldev->dev, "Value 0x%0llx out of range\n", val); 390 + return -EINVAL; 391 + } 392 + 393 + put_unaligned_be48(val, buf); 394 + 395 + return zl3073x_write_reg(zldev, reg, buf, sizeof(buf)); 396 + } 397 + 398 + /** 399 + * zl3073x_poll_zero_u8 - wait for register to be cleared by device 400 + * @zldev: zl3073x device pointer 401 + * @reg: register to poll (has to be 8bit register) 402 + * @mask: bit mask for polling 403 + * 404 + * Waits for bits specified by @mask in register @reg value to be cleared 405 + * by the device. 406 + * 407 + * Returns: 0 on success, <0 on error 408 + */ 409 + int zl3073x_poll_zero_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 mask) 410 + { 411 + /* Register polling sleep & timeout */ 412 + #define ZL_POLL_SLEEP_US 10 413 + #define ZL_POLL_TIMEOUT_US 2000000 414 + unsigned int val; 415 + 416 + /* Check the register is 8bit */ 417 + if (ZL_REG_SIZE(reg) != 1) { 418 + dev_err(zldev->dev, "Invalid reg 0x%04lx size for polling\n", 419 + ZL_REG_ADDR(reg)); 420 + return -EINVAL; 421 + } 422 + 423 + /* Map the register address to virtual range */ 424 + reg = ZL_REG_ADDR(reg) + ZL_RANGE_OFFSET; 425 + 426 + return regmap_read_poll_timeout(zldev->regmap, reg, val, !(val & mask), 427 + ZL_POLL_SLEEP_US, ZL_POLL_TIMEOUT_US); 428 + } 429 + 430 + int zl3073x_mb_op(struct zl3073x_dev *zldev, unsigned int op_reg, u8 op_val, 431 + unsigned int mask_reg, u16 mask_val) 432 + { 433 + int rc; 434 + 435 + /* Set mask for the operation */ 436 + rc = zl3073x_write_u16(zldev, mask_reg, mask_val); 437 + if (rc) 438 + return rc; 439 + 440 + /* Trigger the operation */ 441 + rc = zl3073x_write_u8(zldev, op_reg, op_val); 442 + if (rc) 443 + return rc; 444 + 445 + /* Wait for the operation to actually finish */ 446 + return zl3073x_poll_zero_u8(zldev, op_reg, op_val); 447 + } 448 + 449 + /** 450 + * zl3073x_ref_state_fetch - get input reference state 451 + * @zldev: pointer to zl3073x_dev structure 452 + * @index: input reference index to fetch state for 453 + * 454 + * Function fetches information for the given input reference that are 455 + * invariant and stores them for later use. 456 + * 457 + * Return: 0 on success, <0 on error 458 + */ 459 + static int 460 + zl3073x_ref_state_fetch(struct zl3073x_dev *zldev, u8 index) 461 + { 462 + struct zl3073x_ref *input = &zldev->ref[index]; 463 + u8 ref_config; 464 + int rc; 465 + 466 + /* If the input is differential then the configuration for N-pin 467 + * reference is ignored and P-pin config is used for both. 468 + */ 469 + if (zl3073x_is_n_pin(index) && 470 + zl3073x_ref_is_diff(zldev, index - 1)) { 471 + input->enabled = zl3073x_ref_is_enabled(zldev, index - 1); 472 + input->diff = true; 473 + 474 + return 0; 475 + } 476 + 477 + guard(mutex)(&zldev->multiop_lock); 478 + 479 + /* Read reference configuration */ 480 + rc = zl3073x_mb_op(zldev, ZL_REG_REF_MB_SEM, ZL_REF_MB_SEM_RD, 481 + ZL_REG_REF_MB_MASK, BIT(index)); 482 + if (rc) 483 + return rc; 484 + 485 + /* Read ref_config register */ 486 + rc = zl3073x_read_u8(zldev, ZL_REG_REF_CONFIG, &ref_config); 487 + if (rc) 488 + return rc; 489 + 490 + input->enabled = FIELD_GET(ZL_REF_CONFIG_ENABLE, ref_config); 491 + input->diff = FIELD_GET(ZL_REF_CONFIG_DIFF_EN, ref_config); 492 + 493 + dev_dbg(zldev->dev, "REF%u is %s and configured as %s\n", index, 494 + str_enabled_disabled(input->enabled), 495 + input->diff ? "differential" : "single-ended"); 496 + 497 + return rc; 498 + } 499 + 500 + /** 501 + * zl3073x_out_state_fetch - get output state 502 + * @zldev: pointer to zl3073x_dev structure 503 + * @index: output index to fetch state for 504 + * 505 + * Function fetches information for the given output (not output pin) 506 + * that are invariant and stores them for later use. 507 + * 508 + * Return: 0 on success, <0 on error 509 + */ 510 + static int 511 + zl3073x_out_state_fetch(struct zl3073x_dev *zldev, u8 index) 512 + { 513 + struct zl3073x_out *out = &zldev->out[index]; 514 + u8 output_ctrl, output_mode; 515 + int rc; 516 + 517 + /* Read output configuration */ 518 + rc = zl3073x_read_u8(zldev, ZL_REG_OUTPUT_CTRL(index), &output_ctrl); 519 + if (rc) 520 + return rc; 521 + 522 + /* Store info about output enablement and synthesizer the output 523 + * is connected to. 524 + */ 525 + out->enabled = FIELD_GET(ZL_OUTPUT_CTRL_EN, output_ctrl); 526 + out->synth = FIELD_GET(ZL_OUTPUT_CTRL_SYNTH_SEL, output_ctrl); 527 + 528 + dev_dbg(zldev->dev, "OUT%u is %s and connected to SYNTH%u\n", index, 529 + str_enabled_disabled(out->enabled), out->synth); 530 + 531 + guard(mutex)(&zldev->multiop_lock); 532 + 533 + /* Read output configuration */ 534 + rc = zl3073x_mb_op(zldev, ZL_REG_OUTPUT_MB_SEM, ZL_OUTPUT_MB_SEM_RD, 535 + ZL_REG_OUTPUT_MB_MASK, BIT(index)); 536 + if (rc) 537 + return rc; 538 + 539 + /* Read output_mode */ 540 + rc = zl3073x_read_u8(zldev, ZL_REG_OUTPUT_MODE, &output_mode); 541 + if (rc) 542 + return rc; 543 + 544 + /* Extract and store output signal format */ 545 + out->signal_format = FIELD_GET(ZL_OUTPUT_MODE_SIGNAL_FORMAT, 546 + output_mode); 547 + 548 + dev_dbg(zldev->dev, "OUT%u has signal format 0x%02x\n", index, 549 + out->signal_format); 550 + 551 + return rc; 552 + } 553 + 554 + /** 555 + * zl3073x_synth_state_fetch - get synth state 556 + * @zldev: pointer to zl3073x_dev structure 557 + * @index: synth index to fetch state for 558 + * 559 + * Function fetches information for the given synthesizer that are 560 + * invariant and stores them for later use. 561 + * 562 + * Return: 0 on success, <0 on error 563 + */ 564 + static int 565 + zl3073x_synth_state_fetch(struct zl3073x_dev *zldev, u8 index) 566 + { 567 + struct zl3073x_synth *synth = &zldev->synth[index]; 568 + u16 base, m, n; 569 + u8 synth_ctrl; 570 + u32 mult; 571 + int rc; 572 + 573 + /* Read synth control register */ 574 + rc = zl3073x_read_u8(zldev, ZL_REG_SYNTH_CTRL(index), &synth_ctrl); 575 + if (rc) 576 + return rc; 577 + 578 + /* Store info about synth enablement and DPLL channel the synth is 579 + * driven by. 580 + */ 581 + synth->enabled = FIELD_GET(ZL_SYNTH_CTRL_EN, synth_ctrl); 582 + synth->dpll = FIELD_GET(ZL_SYNTH_CTRL_DPLL_SEL, synth_ctrl); 583 + 584 + dev_dbg(zldev->dev, "SYNTH%u is %s and driven by DPLL%u\n", index, 585 + str_enabled_disabled(synth->enabled), synth->dpll); 586 + 587 + guard(mutex)(&zldev->multiop_lock); 588 + 589 + /* Read synth configuration */ 590 + rc = zl3073x_mb_op(zldev, ZL_REG_SYNTH_MB_SEM, ZL_SYNTH_MB_SEM_RD, 591 + ZL_REG_SYNTH_MB_MASK, BIT(index)); 592 + if (rc) 593 + return rc; 594 + 595 + /* The output frequency is determined by the following formula: 596 + * base * multiplier * numerator / denominator 597 + * 598 + * Read registers with these values 599 + */ 600 + rc = zl3073x_read_u16(zldev, ZL_REG_SYNTH_FREQ_BASE, &base); 601 + if (rc) 602 + return rc; 603 + 604 + rc = zl3073x_read_u32(zldev, ZL_REG_SYNTH_FREQ_MULT, &mult); 605 + if (rc) 606 + return rc; 607 + 608 + rc = zl3073x_read_u16(zldev, ZL_REG_SYNTH_FREQ_M, &m); 609 + if (rc) 610 + return rc; 611 + 612 + rc = zl3073x_read_u16(zldev, ZL_REG_SYNTH_FREQ_N, &n); 613 + if (rc) 614 + return rc; 615 + 616 + /* Check denominator for zero to avoid div by 0 */ 617 + if (!n) { 618 + dev_err(zldev->dev, 619 + "Zero divisor for SYNTH%u retrieved from device\n", 620 + index); 621 + return -EINVAL; 622 + } 623 + 624 + /* Compute and store synth frequency */ 625 + zldev->synth[index].freq = div_u64(mul_u32_u32(base * m, mult), n); 626 + 627 + dev_dbg(zldev->dev, "SYNTH%u frequency: %u Hz\n", index, 628 + zldev->synth[index].freq); 629 + 630 + return rc; 631 + } 632 + 633 + static int 634 + zl3073x_dev_state_fetch(struct zl3073x_dev *zldev) 635 + { 636 + int rc; 637 + u8 i; 638 + 639 + for (i = 0; i < ZL3073X_NUM_REFS; i++) { 640 + rc = zl3073x_ref_state_fetch(zldev, i); 641 + if (rc) { 642 + dev_err(zldev->dev, 643 + "Failed to fetch input state: %pe\n", 644 + ERR_PTR(rc)); 645 + return rc; 646 + } 647 + } 648 + 649 + for (i = 0; i < ZL3073X_NUM_SYNTHS; i++) { 650 + rc = zl3073x_synth_state_fetch(zldev, i); 651 + if (rc) { 652 + dev_err(zldev->dev, 653 + "Failed to fetch synth state: %pe\n", 654 + ERR_PTR(rc)); 655 + return rc; 656 + } 657 + } 658 + 659 + for (i = 0; i < ZL3073X_NUM_OUTS; i++) { 660 + rc = zl3073x_out_state_fetch(zldev, i); 661 + if (rc) { 662 + dev_err(zldev->dev, 663 + "Failed to fetch output state: %pe\n", 664 + ERR_PTR(rc)); 665 + return rc; 666 + } 667 + } 668 + 669 + return rc; 670 + } 671 + 672 + static void 673 + zl3073x_dev_periodic_work(struct kthread_work *work) 674 + { 675 + struct zl3073x_dev *zldev = container_of(work, struct zl3073x_dev, 676 + work.work); 677 + struct zl3073x_dpll *zldpll; 678 + 679 + list_for_each_entry(zldpll, &zldev->dplls, list) 680 + zl3073x_dpll_changes_check(zldpll); 681 + 682 + /* Run twice a second */ 683 + kthread_queue_delayed_work(zldev->kworker, &zldev->work, 684 + msecs_to_jiffies(500)); 685 + } 686 + 687 + static void zl3073x_dev_dpll_fini(void *ptr) 688 + { 689 + struct zl3073x_dpll *zldpll, *next; 690 + struct zl3073x_dev *zldev = ptr; 691 + 692 + /* Stop monitoring thread */ 693 + if (zldev->kworker) { 694 + kthread_cancel_delayed_work_sync(&zldev->work); 695 + kthread_destroy_worker(zldev->kworker); 696 + zldev->kworker = NULL; 697 + } 698 + 699 + /* Release DPLLs */ 700 + list_for_each_entry_safe(zldpll, next, &zldev->dplls, list) { 701 + zl3073x_dpll_unregister(zldpll); 702 + list_del(&zldpll->list); 703 + zl3073x_dpll_free(zldpll); 704 + } 705 + } 706 + 707 + static int 708 + zl3073x_devm_dpll_init(struct zl3073x_dev *zldev, u8 num_dplls) 709 + { 710 + struct kthread_worker *kworker; 711 + struct zl3073x_dpll *zldpll; 712 + unsigned int i; 713 + int rc; 714 + 715 + INIT_LIST_HEAD(&zldev->dplls); 716 + 717 + /* Initialize all DPLLs */ 718 + for (i = 0; i < num_dplls; i++) { 719 + zldpll = zl3073x_dpll_alloc(zldev, i); 720 + if (IS_ERR(zldpll)) { 721 + dev_err_probe(zldev->dev, PTR_ERR(zldpll), 722 + "Failed to alloc DPLL%u\n", i); 723 + rc = PTR_ERR(zldpll); 724 + goto error; 725 + } 726 + 727 + rc = zl3073x_dpll_register(zldpll); 728 + if (rc) { 729 + dev_err_probe(zldev->dev, rc, 730 + "Failed to register DPLL%u\n", i); 731 + zl3073x_dpll_free(zldpll); 732 + goto error; 733 + } 734 + 735 + list_add_tail(&zldpll->list, &zldev->dplls); 736 + } 737 + 738 + /* Perform initial firmware fine phase correction */ 739 + rc = zl3073x_dpll_init_fine_phase_adjust(zldev); 740 + if (rc) { 741 + dev_err_probe(zldev->dev, rc, 742 + "Failed to init fine phase correction\n"); 743 + goto error; 744 + } 745 + 746 + /* Initialize monitoring thread */ 747 + kthread_init_delayed_work(&zldev->work, zl3073x_dev_periodic_work); 748 + kworker = kthread_run_worker(0, "zl3073x-%s", dev_name(zldev->dev)); 749 + if (IS_ERR(kworker)) { 750 + rc = PTR_ERR(kworker); 751 + goto error; 752 + } 753 + 754 + zldev->kworker = kworker; 755 + kthread_queue_delayed_work(zldev->kworker, &zldev->work, 0); 756 + 757 + /* Add devres action to release DPLL related resources */ 758 + rc = devm_add_action_or_reset(zldev->dev, zl3073x_dev_dpll_fini, zldev); 759 + if (rc) 760 + goto error; 761 + 762 + return 0; 763 + 764 + error: 765 + zl3073x_dev_dpll_fini(zldev); 766 + 767 + return rc; 768 + } 769 + 770 + /** 771 + * zl3073x_dev_probe - initialize zl3073x device 772 + * @zldev: pointer to zl3073x device 773 + * @chip_info: chip info based on compatible 774 + * 775 + * Common initialization of zl3073x device structure. 776 + * 777 + * Returns: 0 on success, <0 on error 778 + */ 779 + int zl3073x_dev_probe(struct zl3073x_dev *zldev, 780 + const struct zl3073x_chip_info *chip_info) 781 + { 782 + u16 id, revision, fw_ver; 783 + unsigned int i; 784 + u32 cfg_ver; 785 + int rc; 786 + 787 + /* Read chip ID */ 788 + rc = zl3073x_read_u16(zldev, ZL_REG_ID, &id); 789 + if (rc) 790 + return rc; 791 + 792 + /* Check it matches */ 793 + for (i = 0; i < chip_info->num_ids; i++) { 794 + if (id == chip_info->ids[i]) 795 + break; 796 + } 797 + 798 + if (i == chip_info->num_ids) { 799 + return dev_err_probe(zldev->dev, -ENODEV, 800 + "Unknown or non-match chip ID: 0x%0x\n", 801 + id); 802 + } 803 + 804 + /* Read revision, firmware version and custom config version */ 805 + rc = zl3073x_read_u16(zldev, ZL_REG_REVISION, &revision); 806 + if (rc) 807 + return rc; 808 + rc = zl3073x_read_u16(zldev, ZL_REG_FW_VER, &fw_ver); 809 + if (rc) 810 + return rc; 811 + rc = zl3073x_read_u32(zldev, ZL_REG_CUSTOM_CONFIG_VER, &cfg_ver); 812 + if (rc) 813 + return rc; 814 + 815 + dev_dbg(zldev->dev, "ChipID(%X), ChipRev(%X), FwVer(%u)\n", id, 816 + revision, fw_ver); 817 + dev_dbg(zldev->dev, "Custom config version: %lu.%lu.%lu.%lu\n", 818 + FIELD_GET(GENMASK(31, 24), cfg_ver), 819 + FIELD_GET(GENMASK(23, 16), cfg_ver), 820 + FIELD_GET(GENMASK(15, 8), cfg_ver), 821 + FIELD_GET(GENMASK(7, 0), cfg_ver)); 822 + 823 + /* Generate random clock ID as the device has not such property that 824 + * could be used for this purpose. A user can later change this value 825 + * using devlink. 826 + */ 827 + zldev->clock_id = get_random_u64(); 828 + 829 + /* Initialize mutex for operations where multiple reads, writes 830 + * and/or polls are required to be done atomically. 831 + */ 832 + rc = devm_mutex_init(zldev->dev, &zldev->multiop_lock); 833 + if (rc) 834 + return dev_err_probe(zldev->dev, rc, 835 + "Failed to initialize mutex\n"); 836 + 837 + /* Fetch device state */ 838 + rc = zl3073x_dev_state_fetch(zldev); 839 + if (rc) 840 + return rc; 841 + 842 + /* Register DPLL channels */ 843 + rc = zl3073x_devm_dpll_init(zldev, chip_info->num_channels); 844 + if (rc) 845 + return rc; 846 + 847 + /* Register the devlink instance and parameters */ 848 + rc = zl3073x_devlink_register(zldev); 849 + if (rc) 850 + return dev_err_probe(zldev->dev, rc, 851 + "Failed to register devlink instance\n"); 852 + 853 + return 0; 854 + } 855 + EXPORT_SYMBOL_NS_GPL(zl3073x_dev_probe, "ZL3073X"); 856 + 857 + MODULE_AUTHOR("Ivan Vecera <ivecera@redhat.com>"); 858 + MODULE_DESCRIPTION("Microchip ZL3073x core driver"); 859 + MODULE_LICENSE("GPL");
+367
drivers/dpll/zl3073x/core.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + 3 + #ifndef _ZL3073X_CORE_H 4 + #define _ZL3073X_CORE_H 5 + 6 + #include <linux/kthread.h> 7 + #include <linux/list.h> 8 + #include <linux/mutex.h> 9 + #include <linux/types.h> 10 + 11 + #include "regs.h" 12 + 13 + struct device; 14 + struct regmap; 15 + struct zl3073x_dpll; 16 + 17 + /* 18 + * Hardware limits for ZL3073x chip family 19 + */ 20 + #define ZL3073X_MAX_CHANNELS 5 21 + #define ZL3073X_NUM_REFS 10 22 + #define ZL3073X_NUM_OUTS 10 23 + #define ZL3073X_NUM_SYNTHS 5 24 + #define ZL3073X_NUM_INPUT_PINS ZL3073X_NUM_REFS 25 + #define ZL3073X_NUM_OUTPUT_PINS (ZL3073X_NUM_OUTS * 2) 26 + #define ZL3073X_NUM_PINS (ZL3073X_NUM_INPUT_PINS + \ 27 + ZL3073X_NUM_OUTPUT_PINS) 28 + 29 + /** 30 + * struct zl3073x_ref - input reference invariant info 31 + * @enabled: input reference is enabled or disabled 32 + * @diff: true if input reference is differential 33 + */ 34 + struct zl3073x_ref { 35 + bool enabled; 36 + bool diff; 37 + }; 38 + 39 + /** 40 + * struct zl3073x_out - output invariant info 41 + * @enabled: out is enabled or disabled 42 + * @synth: synthesizer the out is connected to 43 + * @signal_format: out signal format 44 + */ 45 + struct zl3073x_out { 46 + bool enabled; 47 + u8 synth; 48 + u8 signal_format; 49 + }; 50 + 51 + /** 52 + * struct zl3073x_synth - synthesizer invariant info 53 + * @freq: synthesizer frequency 54 + * @dpll: ID of DPLL the synthesizer is driven by 55 + * @enabled: synth is enabled or disabled 56 + */ 57 + struct zl3073x_synth { 58 + u32 freq; 59 + u8 dpll; 60 + bool enabled; 61 + }; 62 + 63 + /** 64 + * struct zl3073x_dev - zl3073x device 65 + * @dev: pointer to device 66 + * @regmap: regmap to access device registers 67 + * @multiop_lock: to serialize multiple register operations 68 + * @clock_id: clock id of the device 69 + * @ref: array of input references' invariants 70 + * @out: array of outs' invariants 71 + * @synth: array of synths' invariants 72 + * @dplls: list of DPLLs 73 + * @kworker: thread for periodic work 74 + * @work: periodic work 75 + */ 76 + struct zl3073x_dev { 77 + struct device *dev; 78 + struct regmap *regmap; 79 + struct mutex multiop_lock; 80 + u64 clock_id; 81 + 82 + /* Invariants */ 83 + struct zl3073x_ref ref[ZL3073X_NUM_REFS]; 84 + struct zl3073x_out out[ZL3073X_NUM_OUTS]; 85 + struct zl3073x_synth synth[ZL3073X_NUM_SYNTHS]; 86 + 87 + /* DPLL channels */ 88 + struct list_head dplls; 89 + 90 + /* Monitor */ 91 + struct kthread_worker *kworker; 92 + struct kthread_delayed_work work; 93 + }; 94 + 95 + struct zl3073x_chip_info { 96 + const u16 *ids; 97 + size_t num_ids; 98 + int num_channels; 99 + }; 100 + 101 + extern const struct zl3073x_chip_info zl30731_chip_info; 102 + extern const struct zl3073x_chip_info zl30732_chip_info; 103 + extern const struct zl3073x_chip_info zl30733_chip_info; 104 + extern const struct zl3073x_chip_info zl30734_chip_info; 105 + extern const struct zl3073x_chip_info zl30735_chip_info; 106 + extern const struct regmap_config zl3073x_regmap_config; 107 + 108 + struct zl3073x_dev *zl3073x_devm_alloc(struct device *dev); 109 + int zl3073x_dev_probe(struct zl3073x_dev *zldev, 110 + const struct zl3073x_chip_info *chip_info); 111 + 112 + /********************** 113 + * Registers operations 114 + **********************/ 115 + 116 + int zl3073x_mb_op(struct zl3073x_dev *zldev, unsigned int op_reg, u8 op_val, 117 + unsigned int mask_reg, u16 mask_val); 118 + int zl3073x_poll_zero_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 mask); 119 + int zl3073x_read_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 *val); 120 + int zl3073x_read_u16(struct zl3073x_dev *zldev, unsigned int reg, u16 *val); 121 + int zl3073x_read_u32(struct zl3073x_dev *zldev, unsigned int reg, u32 *val); 122 + int zl3073x_read_u48(struct zl3073x_dev *zldev, unsigned int reg, u64 *val); 123 + int zl3073x_write_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 val); 124 + int zl3073x_write_u16(struct zl3073x_dev *zldev, unsigned int reg, u16 val); 125 + int zl3073x_write_u32(struct zl3073x_dev *zldev, unsigned int reg, u32 val); 126 + int zl3073x_write_u48(struct zl3073x_dev *zldev, unsigned int reg, u64 val); 127 + 128 + /***************** 129 + * Misc operations 130 + *****************/ 131 + 132 + int zl3073x_ref_freq_factorize(u32 freq, u16 *base, u16 *mult); 133 + 134 + static inline bool 135 + zl3073x_is_n_pin(u8 id) 136 + { 137 + /* P-pins ids are even while N-pins are odd */ 138 + return id & 1; 139 + } 140 + 141 + static inline bool 142 + zl3073x_is_p_pin(u8 id) 143 + { 144 + return !zl3073x_is_n_pin(id); 145 + } 146 + 147 + /** 148 + * zl3073x_input_pin_ref_get - get reference for given input pin 149 + * @id: input pin id 150 + * 151 + * Return: reference id for the given input pin 152 + */ 153 + static inline u8 154 + zl3073x_input_pin_ref_get(u8 id) 155 + { 156 + return id; 157 + } 158 + 159 + /** 160 + * zl3073x_output_pin_out_get - get output for the given output pin 161 + * @id: output pin id 162 + * 163 + * Return: output id for the given output pin 164 + */ 165 + static inline u8 166 + zl3073x_output_pin_out_get(u8 id) 167 + { 168 + /* Output pin pair shares the single output */ 169 + return id / 2; 170 + } 171 + 172 + /** 173 + * zl3073x_ref_is_diff - check if the given input reference is differential 174 + * @zldev: pointer to zl3073x device 175 + * @index: input reference index 176 + * 177 + * Return: true if reference is differential, false if reference is single-ended 178 + */ 179 + static inline bool 180 + zl3073x_ref_is_diff(struct zl3073x_dev *zldev, u8 index) 181 + { 182 + return zldev->ref[index].diff; 183 + } 184 + 185 + /** 186 + * zl3073x_ref_is_enabled - check if the given input reference is enabled 187 + * @zldev: pointer to zl3073x device 188 + * @index: input reference index 189 + * 190 + * Return: true if input refernce is enabled, false otherwise 191 + */ 192 + static inline bool 193 + zl3073x_ref_is_enabled(struct zl3073x_dev *zldev, u8 index) 194 + { 195 + return zldev->ref[index].enabled; 196 + } 197 + 198 + /** 199 + * zl3073x_synth_dpll_get - get DPLL ID the synth is driven by 200 + * @zldev: pointer to zl3073x device 201 + * @index: synth index 202 + * 203 + * Return: ID of DPLL the given synthetizer is driven by 204 + */ 205 + static inline u8 206 + zl3073x_synth_dpll_get(struct zl3073x_dev *zldev, u8 index) 207 + { 208 + return zldev->synth[index].dpll; 209 + } 210 + 211 + /** 212 + * zl3073x_synth_freq_get - get synth current freq 213 + * @zldev: pointer to zl3073x device 214 + * @index: synth index 215 + * 216 + * Return: frequency of given synthetizer 217 + */ 218 + static inline u32 219 + zl3073x_synth_freq_get(struct zl3073x_dev *zldev, u8 index) 220 + { 221 + return zldev->synth[index].freq; 222 + } 223 + 224 + /** 225 + * zl3073x_synth_is_enabled - check if the given synth is enabled 226 + * @zldev: pointer to zl3073x device 227 + * @index: synth index 228 + * 229 + * Return: true if synth is enabled, false otherwise 230 + */ 231 + static inline bool 232 + zl3073x_synth_is_enabled(struct zl3073x_dev *zldev, u8 index) 233 + { 234 + return zldev->synth[index].enabled; 235 + } 236 + 237 + /** 238 + * zl3073x_out_synth_get - get synth connected to given output 239 + * @zldev: pointer to zl3073x device 240 + * @index: output index 241 + * 242 + * Return: index of synth connected to given output. 243 + */ 244 + static inline u8 245 + zl3073x_out_synth_get(struct zl3073x_dev *zldev, u8 index) 246 + { 247 + return zldev->out[index].synth; 248 + } 249 + 250 + /** 251 + * zl3073x_out_is_enabled - check if the given output is enabled 252 + * @zldev: pointer to zl3073x device 253 + * @index: output index 254 + * 255 + * Return: true if the output is enabled, false otherwise 256 + */ 257 + static inline bool 258 + zl3073x_out_is_enabled(struct zl3073x_dev *zldev, u8 index) 259 + { 260 + u8 synth; 261 + 262 + /* Output is enabled only if associated synth is enabled */ 263 + synth = zl3073x_out_synth_get(zldev, index); 264 + if (zl3073x_synth_is_enabled(zldev, synth)) 265 + return zldev->out[index].enabled; 266 + 267 + return false; 268 + } 269 + 270 + /** 271 + * zl3073x_out_signal_format_get - get output signal format 272 + * @zldev: pointer to zl3073x device 273 + * @index: output index 274 + * 275 + * Return: signal format of given output 276 + */ 277 + static inline u8 278 + zl3073x_out_signal_format_get(struct zl3073x_dev *zldev, u8 index) 279 + { 280 + return zldev->out[index].signal_format; 281 + } 282 + 283 + /** 284 + * zl3073x_out_dpll_get - get DPLL ID the output is driven by 285 + * @zldev: pointer to zl3073x device 286 + * @index: output index 287 + * 288 + * Return: ID of DPLL the given output is driven by 289 + */ 290 + static inline 291 + u8 zl3073x_out_dpll_get(struct zl3073x_dev *zldev, u8 index) 292 + { 293 + u8 synth; 294 + 295 + /* Get synthesizer connected to given output */ 296 + synth = zl3073x_out_synth_get(zldev, index); 297 + 298 + /* Return DPLL that drives the synth */ 299 + return zl3073x_synth_dpll_get(zldev, synth); 300 + } 301 + 302 + /** 303 + * zl3073x_out_is_diff - check if the given output is differential 304 + * @zldev: pointer to zl3073x device 305 + * @index: output index 306 + * 307 + * Return: true if output is differential, false if output is single-ended 308 + */ 309 + static inline bool 310 + zl3073x_out_is_diff(struct zl3073x_dev *zldev, u8 index) 311 + { 312 + switch (zl3073x_out_signal_format_get(zldev, index)) { 313 + case ZL_OUTPUT_MODE_SIGNAL_FORMAT_LVDS: 314 + case ZL_OUTPUT_MODE_SIGNAL_FORMAT_DIFF: 315 + case ZL_OUTPUT_MODE_SIGNAL_FORMAT_LOWVCM: 316 + return true; 317 + default: 318 + break; 319 + } 320 + 321 + return false; 322 + } 323 + 324 + /** 325 + * zl3073x_output_pin_is_enabled - check if the given output pin is enabled 326 + * @zldev: pointer to zl3073x device 327 + * @id: output pin id 328 + * 329 + * Checks if the output of the given output pin is enabled and also that 330 + * its signal format also enables the given pin. 331 + * 332 + * Return: true if output pin is enabled, false if output pin is disabled 333 + */ 334 + static inline bool 335 + zl3073x_output_pin_is_enabled(struct zl3073x_dev *zldev, u8 id) 336 + { 337 + u8 output = zl3073x_output_pin_out_get(id); 338 + 339 + /* Check if the whole output is enabled */ 340 + if (!zl3073x_out_is_enabled(zldev, output)) 341 + return false; 342 + 343 + /* Check signal format */ 344 + switch (zl3073x_out_signal_format_get(zldev, output)) { 345 + case ZL_OUTPUT_MODE_SIGNAL_FORMAT_DISABLED: 346 + /* Both output pins are disabled by signal format */ 347 + return false; 348 + 349 + case ZL_OUTPUT_MODE_SIGNAL_FORMAT_1P: 350 + /* Output is one single ended P-pin output */ 351 + if (zl3073x_is_n_pin(id)) 352 + return false; 353 + break; 354 + case ZL_OUTPUT_MODE_SIGNAL_FORMAT_1N: 355 + /* Output is one single ended N-pin output */ 356 + if (zl3073x_is_p_pin(id)) 357 + return false; 358 + break; 359 + default: 360 + /* For other format both pins are enabled */ 361 + break; 362 + } 363 + 364 + return true; 365 + } 366 + 367 + #endif /* _ZL3073X_CORE_H */
+259
drivers/dpll/zl3073x/devlink.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + 3 + #include <linux/device/devres.h> 4 + #include <linux/netlink.h> 5 + #include <linux/sprintf.h> 6 + #include <linux/types.h> 7 + #include <net/devlink.h> 8 + 9 + #include "core.h" 10 + #include "devlink.h" 11 + #include "dpll.h" 12 + #include "regs.h" 13 + 14 + /** 15 + * zl3073x_devlink_info_get - Devlink device info callback 16 + * @devlink: devlink structure pointer 17 + * @req: devlink request pointer to store information 18 + * @extack: netlink extack pointer to report errors 19 + * 20 + * Return: 0 on success, <0 on error 21 + */ 22 + static int 23 + zl3073x_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req, 24 + struct netlink_ext_ack *extack) 25 + { 26 + struct zl3073x_dev *zldev = devlink_priv(devlink); 27 + u16 id, revision, fw_ver; 28 + char buf[16]; 29 + u32 cfg_ver; 30 + int rc; 31 + 32 + rc = zl3073x_read_u16(zldev, ZL_REG_ID, &id); 33 + if (rc) 34 + return rc; 35 + 36 + snprintf(buf, sizeof(buf), "%X", id); 37 + rc = devlink_info_version_fixed_put(req, 38 + DEVLINK_INFO_VERSION_GENERIC_ASIC_ID, 39 + buf); 40 + if (rc) 41 + return rc; 42 + 43 + rc = zl3073x_read_u16(zldev, ZL_REG_REVISION, &revision); 44 + if (rc) 45 + return rc; 46 + 47 + snprintf(buf, sizeof(buf), "%X", revision); 48 + rc = devlink_info_version_fixed_put(req, 49 + DEVLINK_INFO_VERSION_GENERIC_ASIC_REV, 50 + buf); 51 + if (rc) 52 + return rc; 53 + 54 + rc = zl3073x_read_u16(zldev, ZL_REG_FW_VER, &fw_ver); 55 + if (rc) 56 + return rc; 57 + 58 + snprintf(buf, sizeof(buf), "%u", fw_ver); 59 + rc = devlink_info_version_running_put(req, 60 + DEVLINK_INFO_VERSION_GENERIC_FW, 61 + buf); 62 + if (rc) 63 + return rc; 64 + 65 + rc = zl3073x_read_u32(zldev, ZL_REG_CUSTOM_CONFIG_VER, &cfg_ver); 66 + if (rc) 67 + return rc; 68 + 69 + /* No custom config version */ 70 + if (cfg_ver == U32_MAX) 71 + return 0; 72 + 73 + snprintf(buf, sizeof(buf), "%lu.%lu.%lu.%lu", 74 + FIELD_GET(GENMASK(31, 24), cfg_ver), 75 + FIELD_GET(GENMASK(23, 16), cfg_ver), 76 + FIELD_GET(GENMASK(15, 8), cfg_ver), 77 + FIELD_GET(GENMASK(7, 0), cfg_ver)); 78 + 79 + return devlink_info_version_running_put(req, "custom_cfg", buf); 80 + } 81 + 82 + static int 83 + zl3073x_devlink_reload_down(struct devlink *devlink, bool netns_change, 84 + enum devlink_reload_action action, 85 + enum devlink_reload_limit limit, 86 + struct netlink_ext_ack *extack) 87 + { 88 + struct zl3073x_dev *zldev = devlink_priv(devlink); 89 + struct zl3073x_dpll *zldpll; 90 + 91 + if (action != DEVLINK_RELOAD_ACTION_DRIVER_REINIT) 92 + return -EOPNOTSUPP; 93 + 94 + /* Unregister all DPLLs */ 95 + list_for_each_entry(zldpll, &zldev->dplls, list) 96 + zl3073x_dpll_unregister(zldpll); 97 + 98 + return 0; 99 + } 100 + 101 + static int 102 + zl3073x_devlink_reload_up(struct devlink *devlink, 103 + enum devlink_reload_action action, 104 + enum devlink_reload_limit limit, 105 + u32 *actions_performed, 106 + struct netlink_ext_ack *extack) 107 + { 108 + struct zl3073x_dev *zldev = devlink_priv(devlink); 109 + union devlink_param_value val; 110 + struct zl3073x_dpll *zldpll; 111 + int rc; 112 + 113 + if (action != DEVLINK_RELOAD_ACTION_DRIVER_REINIT) 114 + return -EOPNOTSUPP; 115 + 116 + rc = devl_param_driverinit_value_get(devlink, 117 + DEVLINK_PARAM_GENERIC_ID_CLOCK_ID, 118 + &val); 119 + if (rc) 120 + return rc; 121 + 122 + if (zldev->clock_id != val.vu64) { 123 + dev_dbg(zldev->dev, 124 + "'clock_id' changed to %016llx\n", val.vu64); 125 + zldev->clock_id = val.vu64; 126 + } 127 + 128 + /* Re-register all DPLLs */ 129 + list_for_each_entry(zldpll, &zldev->dplls, list) { 130 + rc = zl3073x_dpll_register(zldpll); 131 + if (rc) 132 + dev_warn(zldev->dev, 133 + "Failed to re-register DPLL%u\n", zldpll->id); 134 + } 135 + 136 + *actions_performed = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT); 137 + 138 + return 0; 139 + } 140 + 141 + static const struct devlink_ops zl3073x_devlink_ops = { 142 + .info_get = zl3073x_devlink_info_get, 143 + .reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT), 144 + .reload_down = zl3073x_devlink_reload_down, 145 + .reload_up = zl3073x_devlink_reload_up, 146 + }; 147 + 148 + static void 149 + zl3073x_devlink_free(void *ptr) 150 + { 151 + devlink_free(ptr); 152 + } 153 + 154 + /** 155 + * zl3073x_devm_alloc - allocates zl3073x device structure 156 + * @dev: pointer to device structure 157 + * 158 + * Allocates zl3073x device structure as device resource. 159 + * 160 + * Return: pointer to zl3073x device on success, error pointer on error 161 + */ 162 + struct zl3073x_dev *zl3073x_devm_alloc(struct device *dev) 163 + { 164 + struct zl3073x_dev *zldev; 165 + struct devlink *devlink; 166 + int rc; 167 + 168 + devlink = devlink_alloc(&zl3073x_devlink_ops, sizeof(*zldev), dev); 169 + if (!devlink) 170 + return ERR_PTR(-ENOMEM); 171 + 172 + /* Add devres action to free devlink device */ 173 + rc = devm_add_action_or_reset(dev, zl3073x_devlink_free, devlink); 174 + if (rc) 175 + return ERR_PTR(rc); 176 + 177 + zldev = devlink_priv(devlink); 178 + zldev->dev = dev; 179 + dev_set_drvdata(zldev->dev, zldev); 180 + 181 + return zldev; 182 + } 183 + EXPORT_SYMBOL_NS_GPL(zl3073x_devm_alloc, "ZL3073X"); 184 + 185 + static int 186 + zl3073x_devlink_param_clock_id_validate(struct devlink *devlink, u32 id, 187 + union devlink_param_value val, 188 + struct netlink_ext_ack *extack) 189 + { 190 + if (!val.vu64) { 191 + NL_SET_ERR_MSG_MOD(extack, "'clock_id' must be non-zero"); 192 + return -EINVAL; 193 + } 194 + 195 + return 0; 196 + } 197 + 198 + static const struct devlink_param zl3073x_devlink_params[] = { 199 + DEVLINK_PARAM_GENERIC(CLOCK_ID, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), 200 + NULL, NULL, 201 + zl3073x_devlink_param_clock_id_validate), 202 + }; 203 + 204 + static void 205 + zl3073x_devlink_unregister(void *ptr) 206 + { 207 + struct devlink *devlink = priv_to_devlink(ptr); 208 + 209 + devl_lock(devlink); 210 + 211 + /* Unregister devlink params */ 212 + devl_params_unregister(devlink, zl3073x_devlink_params, 213 + ARRAY_SIZE(zl3073x_devlink_params)); 214 + 215 + /* Unregister devlink instance */ 216 + devl_unregister(devlink); 217 + 218 + devl_unlock(devlink); 219 + } 220 + 221 + /** 222 + * zl3073x_devlink_register - register devlink instance and params 223 + * @zldev: zl3073x device to register the devlink for 224 + * 225 + * Register the devlink instance and parameters associated with the device. 226 + * 227 + * Return: 0 on success, <0 on error 228 + */ 229 + int zl3073x_devlink_register(struct zl3073x_dev *zldev) 230 + { 231 + struct devlink *devlink = priv_to_devlink(zldev); 232 + union devlink_param_value value; 233 + int rc; 234 + 235 + devl_lock(devlink); 236 + 237 + /* Register devlink params */ 238 + rc = devl_params_register(devlink, zl3073x_devlink_params, 239 + ARRAY_SIZE(zl3073x_devlink_params)); 240 + if (rc) { 241 + devl_unlock(devlink); 242 + 243 + return rc; 244 + } 245 + 246 + value.vu64 = zldev->clock_id; 247 + devl_param_driverinit_value_set(devlink, 248 + DEVLINK_PARAM_GENERIC_ID_CLOCK_ID, 249 + value); 250 + 251 + /* Register devlink instance */ 252 + devl_register(devlink); 253 + 254 + devl_unlock(devlink); 255 + 256 + /* Add devres action to unregister devlink device */ 257 + return devm_add_action_or_reset(zldev->dev, zl3073x_devlink_unregister, 258 + zldev); 259 + }
+12
drivers/dpll/zl3073x/devlink.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + 3 + #ifndef _ZL3073X_DEVLINK_H 4 + #define _ZL3073X_DEVLINK_H 5 + 6 + struct zl3073x_dev; 7 + 8 + struct zl3073x_dev *zl3073x_devm_alloc(struct device *dev); 9 + 10 + int zl3073x_devlink_register(struct zl3073x_dev *zldev); 11 + 12 + #endif /* _ZL3073X_DEVLINK_H */
+1504
drivers/dpll/zl3073x/dpll.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + 3 + #include <linux/bits.h> 4 + #include <linux/bitfield.h> 5 + #include <linux/bug.h> 6 + #include <linux/container_of.h> 7 + #include <linux/dev_printk.h> 8 + #include <linux/dpll.h> 9 + #include <linux/err.h> 10 + #include <linux/kthread.h> 11 + #include <linux/math64.h> 12 + #include <linux/mod_devicetable.h> 13 + #include <linux/module.h> 14 + #include <linux/netlink.h> 15 + #include <linux/platform_device.h> 16 + #include <linux/slab.h> 17 + #include <linux/sprintf.h> 18 + 19 + #include "core.h" 20 + #include "dpll.h" 21 + #include "prop.h" 22 + #include "regs.h" 23 + 24 + #define ZL3073X_DPLL_REF_NONE ZL3073X_NUM_REFS 25 + #define ZL3073X_DPLL_REF_IS_VALID(_ref) ((_ref) != ZL3073X_DPLL_REF_NONE) 26 + 27 + /** 28 + * struct zl3073x_dpll_pin - DPLL pin 29 + * @list: this DPLL pin list entry 30 + * @dpll: DPLL the pin is registered to 31 + * @dpll_pin: pointer to registered dpll_pin 32 + * @label: package label 33 + * @dir: pin direction 34 + * @id: pin id 35 + * @prio: pin priority <0, 14> 36 + * @selectable: pin is selectable in automatic mode 37 + * @pin_state: last saved pin state 38 + */ 39 + struct zl3073x_dpll_pin { 40 + struct list_head list; 41 + struct zl3073x_dpll *dpll; 42 + struct dpll_pin *dpll_pin; 43 + char label[8]; 44 + enum dpll_pin_direction dir; 45 + u8 id; 46 + u8 prio; 47 + bool selectable; 48 + enum dpll_pin_state pin_state; 49 + }; 50 + 51 + /** 52 + * zl3073x_dpll_is_input_pin - check if the pin is input one 53 + * @pin: pin to check 54 + * 55 + * Return: true if pin is input, false if pin is output. 56 + */ 57 + static bool 58 + zl3073x_dpll_is_input_pin(struct zl3073x_dpll_pin *pin) 59 + { 60 + return pin->dir == DPLL_PIN_DIRECTION_INPUT; 61 + } 62 + 63 + /** 64 + * zl3073x_dpll_is_p_pin - check if the pin is P-pin 65 + * @pin: pin to check 66 + * 67 + * Return: true if the pin is P-pin, false if it is N-pin 68 + */ 69 + static bool 70 + zl3073x_dpll_is_p_pin(struct zl3073x_dpll_pin *pin) 71 + { 72 + return zl3073x_is_p_pin(pin->id); 73 + } 74 + 75 + static int 76 + zl3073x_dpll_pin_direction_get(const struct dpll_pin *dpll_pin, void *pin_priv, 77 + const struct dpll_device *dpll, void *dpll_priv, 78 + enum dpll_pin_direction *direction, 79 + struct netlink_ext_ack *extack) 80 + { 81 + struct zl3073x_dpll_pin *pin = pin_priv; 82 + 83 + *direction = pin->dir; 84 + 85 + return 0; 86 + } 87 + 88 + /** 89 + * zl3073x_dpll_input_ref_frequency_get - get input reference frequency 90 + * @zldpll: pointer to zl3073x_dpll 91 + * @ref_id: reference id 92 + * @frequency: pointer to variable to store frequency 93 + * 94 + * Reads frequency of given input reference. 95 + * 96 + * Return: 0 on success, <0 on error 97 + */ 98 + static int 99 + zl3073x_dpll_input_ref_frequency_get(struct zl3073x_dpll *zldpll, u8 ref_id, 100 + u32 *frequency) 101 + { 102 + struct zl3073x_dev *zldev = zldpll->dev; 103 + u16 base, mult, num, denom; 104 + int rc; 105 + 106 + guard(mutex)(&zldev->multiop_lock); 107 + 108 + /* Read reference configuration */ 109 + rc = zl3073x_mb_op(zldev, ZL_REG_REF_MB_SEM, ZL_REF_MB_SEM_RD, 110 + ZL_REG_REF_MB_MASK, BIT(ref_id)); 111 + if (rc) 112 + return rc; 113 + 114 + /* Read registers to compute resulting frequency */ 115 + rc = zl3073x_read_u16(zldev, ZL_REG_REF_FREQ_BASE, &base); 116 + if (rc) 117 + return rc; 118 + rc = zl3073x_read_u16(zldev, ZL_REG_REF_FREQ_MULT, &mult); 119 + if (rc) 120 + return rc; 121 + rc = zl3073x_read_u16(zldev, ZL_REG_REF_RATIO_M, &num); 122 + if (rc) 123 + return rc; 124 + rc = zl3073x_read_u16(zldev, ZL_REG_REF_RATIO_N, &denom); 125 + if (rc) 126 + return rc; 127 + 128 + /* Sanity check that HW has not returned zero denominator */ 129 + if (!denom) { 130 + dev_err(zldev->dev, 131 + "Zero divisor for ref %u frequency got from device\n", 132 + ref_id); 133 + return -EINVAL; 134 + } 135 + 136 + /* Compute the frequency */ 137 + *frequency = mul_u64_u32_div(base * mult, num, denom); 138 + 139 + return rc; 140 + } 141 + 142 + static int 143 + zl3073x_dpll_input_pin_frequency_get(const struct dpll_pin *dpll_pin, 144 + void *pin_priv, 145 + const struct dpll_device *dpll, 146 + void *dpll_priv, u64 *frequency, 147 + struct netlink_ext_ack *extack) 148 + { 149 + struct zl3073x_dpll *zldpll = dpll_priv; 150 + struct zl3073x_dpll_pin *pin = pin_priv; 151 + u32 ref_freq; 152 + u8 ref; 153 + int rc; 154 + 155 + /* Read and return ref frequency */ 156 + ref = zl3073x_input_pin_ref_get(pin->id); 157 + rc = zl3073x_dpll_input_ref_frequency_get(zldpll, ref, &ref_freq); 158 + if (!rc) 159 + *frequency = ref_freq; 160 + 161 + return rc; 162 + } 163 + 164 + static int 165 + zl3073x_dpll_input_pin_frequency_set(const struct dpll_pin *dpll_pin, 166 + void *pin_priv, 167 + const struct dpll_device *dpll, 168 + void *dpll_priv, u64 frequency, 169 + struct netlink_ext_ack *extack) 170 + { 171 + struct zl3073x_dpll *zldpll = dpll_priv; 172 + struct zl3073x_dev *zldev = zldpll->dev; 173 + struct zl3073x_dpll_pin *pin = pin_priv; 174 + u16 base, mult; 175 + u8 ref; 176 + int rc; 177 + 178 + /* Get base frequency and multiplier for the requested frequency */ 179 + rc = zl3073x_ref_freq_factorize(frequency, &base, &mult); 180 + if (rc) 181 + return rc; 182 + 183 + guard(mutex)(&zldev->multiop_lock); 184 + 185 + /* Load reference configuration */ 186 + ref = zl3073x_input_pin_ref_get(pin->id); 187 + rc = zl3073x_mb_op(zldev, ZL_REG_REF_MB_SEM, ZL_REF_MB_SEM_RD, 188 + ZL_REG_REF_MB_MASK, BIT(ref)); 189 + 190 + /* Update base frequency, multiplier, numerator & denominator */ 191 + rc = zl3073x_write_u16(zldev, ZL_REG_REF_FREQ_BASE, base); 192 + if (rc) 193 + return rc; 194 + rc = zl3073x_write_u16(zldev, ZL_REG_REF_FREQ_MULT, mult); 195 + if (rc) 196 + return rc; 197 + rc = zl3073x_write_u16(zldev, ZL_REG_REF_RATIO_M, 1); 198 + if (rc) 199 + return rc; 200 + rc = zl3073x_write_u16(zldev, ZL_REG_REF_RATIO_N, 1); 201 + if (rc) 202 + return rc; 203 + 204 + /* Commit reference configuration */ 205 + return zl3073x_mb_op(zldev, ZL_REG_REF_MB_SEM, ZL_REF_MB_SEM_WR, 206 + ZL_REG_REF_MB_MASK, BIT(ref)); 207 + } 208 + 209 + /** 210 + * zl3073x_dpll_selected_ref_get - get currently selected reference 211 + * @zldpll: pointer to zl3073x_dpll 212 + * @ref: place to store selected reference 213 + * 214 + * Check for currently selected reference the DPLL should be locked to 215 + * and stores its index to given @ref. 216 + * 217 + * Return: 0 on success, <0 on error 218 + */ 219 + static int 220 + zl3073x_dpll_selected_ref_get(struct zl3073x_dpll *zldpll, u8 *ref) 221 + { 222 + struct zl3073x_dev *zldev = zldpll->dev; 223 + u8 state, value; 224 + int rc; 225 + 226 + switch (zldpll->refsel_mode) { 227 + case ZL_DPLL_MODE_REFSEL_MODE_AUTO: 228 + /* For automatic mode read refsel_status register */ 229 + rc = zl3073x_read_u8(zldev, 230 + ZL_REG_DPLL_REFSEL_STATUS(zldpll->id), 231 + &value); 232 + if (rc) 233 + return rc; 234 + 235 + /* Extract reference state */ 236 + state = FIELD_GET(ZL_DPLL_REFSEL_STATUS_STATE, value); 237 + 238 + /* Return the reference only if the DPLL is locked to it */ 239 + if (state == ZL_DPLL_REFSEL_STATUS_STATE_LOCK) 240 + *ref = FIELD_GET(ZL_DPLL_REFSEL_STATUS_REFSEL, value); 241 + else 242 + *ref = ZL3073X_DPLL_REF_NONE; 243 + break; 244 + case ZL_DPLL_MODE_REFSEL_MODE_REFLOCK: 245 + /* For manual mode return stored value */ 246 + *ref = zldpll->forced_ref; 247 + break; 248 + default: 249 + /* For other modes like NCO, freerun... there is no input ref */ 250 + *ref = ZL3073X_DPLL_REF_NONE; 251 + break; 252 + } 253 + 254 + return 0; 255 + } 256 + 257 + /** 258 + * zl3073x_dpll_selected_ref_set - select reference in manual mode 259 + * @zldpll: pointer to zl3073x_dpll 260 + * @ref: input reference to be selected 261 + * 262 + * Selects the given reference for the DPLL channel it should be 263 + * locked to. 264 + * 265 + * Return: 0 on success, <0 on error 266 + */ 267 + static int 268 + zl3073x_dpll_selected_ref_set(struct zl3073x_dpll *zldpll, u8 ref) 269 + { 270 + struct zl3073x_dev *zldev = zldpll->dev; 271 + u8 mode, mode_refsel; 272 + int rc; 273 + 274 + mode = zldpll->refsel_mode; 275 + 276 + switch (mode) { 277 + case ZL_DPLL_MODE_REFSEL_MODE_REFLOCK: 278 + /* Manual mode with ref selected */ 279 + if (ref == ZL3073X_DPLL_REF_NONE) { 280 + switch (zldpll->lock_status) { 281 + case DPLL_LOCK_STATUS_LOCKED_HO_ACQ: 282 + case DPLL_LOCK_STATUS_HOLDOVER: 283 + /* Switch to forced holdover */ 284 + mode = ZL_DPLL_MODE_REFSEL_MODE_HOLDOVER; 285 + break; 286 + default: 287 + /* Switch to freerun */ 288 + mode = ZL_DPLL_MODE_REFSEL_MODE_FREERUN; 289 + break; 290 + } 291 + /* Keep selected reference */ 292 + ref = zldpll->forced_ref; 293 + } else if (ref == zldpll->forced_ref) { 294 + /* No register update - same mode and same ref */ 295 + return 0; 296 + } 297 + break; 298 + case ZL_DPLL_MODE_REFSEL_MODE_FREERUN: 299 + case ZL_DPLL_MODE_REFSEL_MODE_HOLDOVER: 300 + /* Manual mode without no ref */ 301 + if (ref == ZL3073X_DPLL_REF_NONE) 302 + /* No register update - keep current mode */ 303 + return 0; 304 + 305 + /* Switch to reflock mode and update ref selection */ 306 + mode = ZL_DPLL_MODE_REFSEL_MODE_REFLOCK; 307 + break; 308 + default: 309 + /* For other modes like automatic or NCO ref cannot be selected 310 + * manually 311 + */ 312 + return -EOPNOTSUPP; 313 + } 314 + 315 + /* Build mode_refsel value */ 316 + mode_refsel = FIELD_PREP(ZL_DPLL_MODE_REFSEL_MODE, mode) | 317 + FIELD_PREP(ZL_DPLL_MODE_REFSEL_REF, ref); 318 + 319 + /* Update dpll_mode_refsel register */ 320 + rc = zl3073x_write_u8(zldev, ZL_REG_DPLL_MODE_REFSEL(zldpll->id), 321 + mode_refsel); 322 + if (rc) 323 + return rc; 324 + 325 + /* Store new mode and forced reference */ 326 + zldpll->refsel_mode = mode; 327 + zldpll->forced_ref = ref; 328 + 329 + return rc; 330 + } 331 + 332 + /** 333 + * zl3073x_dpll_connected_ref_get - get currently connected reference 334 + * @zldpll: pointer to zl3073x_dpll 335 + * @ref: place to store selected reference 336 + * 337 + * Looks for currently connected the DPLL is locked to and stores its index 338 + * to given @ref. 339 + * 340 + * Return: 0 on success, <0 on error 341 + */ 342 + static int 343 + zl3073x_dpll_connected_ref_get(struct zl3073x_dpll *zldpll, u8 *ref) 344 + { 345 + struct zl3073x_dev *zldev = zldpll->dev; 346 + int rc; 347 + 348 + /* Get currently selected input reference */ 349 + rc = zl3073x_dpll_selected_ref_get(zldpll, ref); 350 + if (rc) 351 + return rc; 352 + 353 + if (ZL3073X_DPLL_REF_IS_VALID(*ref)) { 354 + u8 ref_status; 355 + 356 + /* Read the reference monitor status */ 357 + rc = zl3073x_read_u8(zldev, ZL_REG_REF_MON_STATUS(*ref), 358 + &ref_status); 359 + if (rc) 360 + return rc; 361 + 362 + /* If the monitor indicates an error nothing is connected */ 363 + if (ref_status != ZL_REF_MON_STATUS_OK) 364 + *ref = ZL3073X_DPLL_REF_NONE; 365 + } 366 + 367 + return 0; 368 + } 369 + 370 + /** 371 + * zl3073x_dpll_ref_prio_get - get priority for given input pin 372 + * @pin: pointer to pin 373 + * @prio: place to store priority 374 + * 375 + * Reads current priority for the given input pin and stores the value 376 + * to @prio. 377 + * 378 + * Return: 0 on success, <0 on error 379 + */ 380 + static int 381 + zl3073x_dpll_ref_prio_get(struct zl3073x_dpll_pin *pin, u8 *prio) 382 + { 383 + struct zl3073x_dpll *zldpll = pin->dpll; 384 + struct zl3073x_dev *zldev = zldpll->dev; 385 + u8 ref, ref_prio; 386 + int rc; 387 + 388 + guard(mutex)(&zldev->multiop_lock); 389 + 390 + /* Read DPLL configuration */ 391 + rc = zl3073x_mb_op(zldev, ZL_REG_DPLL_MB_SEM, ZL_DPLL_MB_SEM_RD, 392 + ZL_REG_DPLL_MB_MASK, BIT(zldpll->id)); 393 + if (rc) 394 + return rc; 395 + 396 + /* Read reference priority - one value for P&N pins (4 bits/pin) */ 397 + ref = zl3073x_input_pin_ref_get(pin->id); 398 + rc = zl3073x_read_u8(zldev, ZL_REG_DPLL_REF_PRIO(ref / 2), 399 + &ref_prio); 400 + if (rc) 401 + return rc; 402 + 403 + /* Select nibble according pin type */ 404 + if (zl3073x_dpll_is_p_pin(pin)) 405 + *prio = FIELD_GET(ZL_DPLL_REF_PRIO_REF_P, ref_prio); 406 + else 407 + *prio = FIELD_GET(ZL_DPLL_REF_PRIO_REF_N, ref_prio); 408 + 409 + return rc; 410 + } 411 + 412 + /** 413 + * zl3073x_dpll_ref_prio_set - set priority for given input pin 414 + * @pin: pointer to pin 415 + * @prio: place to store priority 416 + * 417 + * Sets priority for the given input pin. 418 + * 419 + * Return: 0 on success, <0 on error 420 + */ 421 + static int 422 + zl3073x_dpll_ref_prio_set(struct zl3073x_dpll_pin *pin, u8 prio) 423 + { 424 + struct zl3073x_dpll *zldpll = pin->dpll; 425 + struct zl3073x_dev *zldev = zldpll->dev; 426 + u8 ref, ref_prio; 427 + int rc; 428 + 429 + guard(mutex)(&zldev->multiop_lock); 430 + 431 + /* Read DPLL configuration into mailbox */ 432 + rc = zl3073x_mb_op(zldev, ZL_REG_DPLL_MB_SEM, ZL_DPLL_MB_SEM_RD, 433 + ZL_REG_DPLL_MB_MASK, BIT(zldpll->id)); 434 + if (rc) 435 + return rc; 436 + 437 + /* Read reference priority - one value shared between P&N pins */ 438 + ref = zl3073x_input_pin_ref_get(pin->id); 439 + rc = zl3073x_read_u8(zldev, ZL_REG_DPLL_REF_PRIO(ref / 2), &ref_prio); 440 + if (rc) 441 + return rc; 442 + 443 + /* Update nibble according pin type */ 444 + if (zl3073x_dpll_is_p_pin(pin)) { 445 + ref_prio &= ~ZL_DPLL_REF_PRIO_REF_P; 446 + ref_prio |= FIELD_PREP(ZL_DPLL_REF_PRIO_REF_P, prio); 447 + } else { 448 + ref_prio &= ~ZL_DPLL_REF_PRIO_REF_N; 449 + ref_prio |= FIELD_PREP(ZL_DPLL_REF_PRIO_REF_N, prio); 450 + } 451 + 452 + /* Update reference priority */ 453 + rc = zl3073x_write_u8(zldev, ZL_REG_DPLL_REF_PRIO(ref / 2), ref_prio); 454 + if (rc) 455 + return rc; 456 + 457 + /* Commit configuration */ 458 + return zl3073x_mb_op(zldev, ZL_REG_DPLL_MB_SEM, ZL_DPLL_MB_SEM_WR, 459 + ZL_REG_DPLL_MB_MASK, BIT(zldpll->id)); 460 + } 461 + 462 + /** 463 + * zl3073x_dpll_ref_state_get - get status for given input pin 464 + * @pin: pointer to pin 465 + * @state: place to store status 466 + * 467 + * Checks current status for the given input pin and stores the value 468 + * to @state. 469 + * 470 + * Return: 0 on success, <0 on error 471 + */ 472 + static int 473 + zl3073x_dpll_ref_state_get(struct zl3073x_dpll_pin *pin, 474 + enum dpll_pin_state *state) 475 + { 476 + struct zl3073x_dpll *zldpll = pin->dpll; 477 + struct zl3073x_dev *zldev = zldpll->dev; 478 + u8 ref, ref_conn, status; 479 + int rc; 480 + 481 + ref = zl3073x_input_pin_ref_get(pin->id); 482 + 483 + /* Get currently connected reference */ 484 + rc = zl3073x_dpll_connected_ref_get(zldpll, &ref_conn); 485 + if (rc) 486 + return rc; 487 + 488 + if (ref == ref_conn) { 489 + *state = DPLL_PIN_STATE_CONNECTED; 490 + return 0; 491 + } 492 + 493 + /* If the DPLL is running in automatic mode and the reference is 494 + * selectable and its monitor does not report any error then report 495 + * pin as selectable. 496 + */ 497 + if (zldpll->refsel_mode == ZL_DPLL_MODE_REFSEL_MODE_AUTO && 498 + pin->selectable) { 499 + /* Read reference monitor status */ 500 + rc = zl3073x_read_u8(zldev, ZL_REG_REF_MON_STATUS(ref), 501 + &status); 502 + if (rc) 503 + return rc; 504 + 505 + /* If the monitor indicates errors report the reference 506 + * as disconnected 507 + */ 508 + if (status == ZL_REF_MON_STATUS_OK) { 509 + *state = DPLL_PIN_STATE_SELECTABLE; 510 + return 0; 511 + } 512 + } 513 + 514 + /* Otherwise report the pin as disconnected */ 515 + *state = DPLL_PIN_STATE_DISCONNECTED; 516 + 517 + return 0; 518 + } 519 + 520 + static int 521 + zl3073x_dpll_input_pin_state_on_dpll_get(const struct dpll_pin *dpll_pin, 522 + void *pin_priv, 523 + const struct dpll_device *dpll, 524 + void *dpll_priv, 525 + enum dpll_pin_state *state, 526 + struct netlink_ext_ack *extack) 527 + { 528 + struct zl3073x_dpll_pin *pin = pin_priv; 529 + 530 + return zl3073x_dpll_ref_state_get(pin, state); 531 + } 532 + 533 + static int 534 + zl3073x_dpll_input_pin_state_on_dpll_set(const struct dpll_pin *dpll_pin, 535 + void *pin_priv, 536 + const struct dpll_device *dpll, 537 + void *dpll_priv, 538 + enum dpll_pin_state state, 539 + struct netlink_ext_ack *extack) 540 + { 541 + struct zl3073x_dpll *zldpll = dpll_priv; 542 + struct zl3073x_dpll_pin *pin = pin_priv; 543 + u8 new_ref; 544 + int rc; 545 + 546 + switch (zldpll->refsel_mode) { 547 + case ZL_DPLL_MODE_REFSEL_MODE_REFLOCK: 548 + case ZL_DPLL_MODE_REFSEL_MODE_FREERUN: 549 + case ZL_DPLL_MODE_REFSEL_MODE_HOLDOVER: 550 + if (state == DPLL_PIN_STATE_CONNECTED) { 551 + /* Choose the pin as new selected reference */ 552 + new_ref = zl3073x_input_pin_ref_get(pin->id); 553 + } else if (state == DPLL_PIN_STATE_DISCONNECTED) { 554 + /* No reference */ 555 + new_ref = ZL3073X_DPLL_REF_NONE; 556 + } else { 557 + NL_SET_ERR_MSG_MOD(extack, 558 + "Invalid pin state for manual mode"); 559 + return -EINVAL; 560 + } 561 + 562 + rc = zl3073x_dpll_selected_ref_set(zldpll, new_ref); 563 + break; 564 + 565 + case ZL_DPLL_MODE_REFSEL_MODE_AUTO: 566 + if (state == DPLL_PIN_STATE_SELECTABLE) { 567 + if (pin->selectable) 568 + return 0; /* Pin is already selectable */ 569 + 570 + /* Restore pin priority in HW */ 571 + rc = zl3073x_dpll_ref_prio_set(pin, pin->prio); 572 + if (rc) 573 + return rc; 574 + 575 + /* Mark pin as selectable */ 576 + pin->selectable = true; 577 + } else if (state == DPLL_PIN_STATE_DISCONNECTED) { 578 + if (!pin->selectable) 579 + return 0; /* Pin is already disconnected */ 580 + 581 + /* Set pin priority to none in HW */ 582 + rc = zl3073x_dpll_ref_prio_set(pin, 583 + ZL_DPLL_REF_PRIO_NONE); 584 + if (rc) 585 + return rc; 586 + 587 + /* Mark pin as non-selectable */ 588 + pin->selectable = false; 589 + } else { 590 + NL_SET_ERR_MSG(extack, 591 + "Invalid pin state for automatic mode"); 592 + return -EINVAL; 593 + } 594 + break; 595 + 596 + default: 597 + /* In other modes we cannot change input reference */ 598 + NL_SET_ERR_MSG(extack, 599 + "Pin state cannot be changed in current mode"); 600 + rc = -EOPNOTSUPP; 601 + break; 602 + } 603 + 604 + return rc; 605 + } 606 + 607 + static int 608 + zl3073x_dpll_input_pin_prio_get(const struct dpll_pin *dpll_pin, void *pin_priv, 609 + const struct dpll_device *dpll, void *dpll_priv, 610 + u32 *prio, struct netlink_ext_ack *extack) 611 + { 612 + struct zl3073x_dpll_pin *pin = pin_priv; 613 + 614 + *prio = pin->prio; 615 + 616 + return 0; 617 + } 618 + 619 + static int 620 + zl3073x_dpll_input_pin_prio_set(const struct dpll_pin *dpll_pin, void *pin_priv, 621 + const struct dpll_device *dpll, void *dpll_priv, 622 + u32 prio, struct netlink_ext_ack *extack) 623 + { 624 + struct zl3073x_dpll_pin *pin = pin_priv; 625 + int rc; 626 + 627 + if (prio > ZL_DPLL_REF_PRIO_MAX) 628 + return -EINVAL; 629 + 630 + /* If the pin is selectable then update HW registers */ 631 + if (pin->selectable) { 632 + rc = zl3073x_dpll_ref_prio_set(pin, prio); 633 + if (rc) 634 + return rc; 635 + } 636 + 637 + /* Save priority */ 638 + pin->prio = prio; 639 + 640 + return 0; 641 + } 642 + 643 + static int 644 + zl3073x_dpll_output_pin_frequency_get(const struct dpll_pin *dpll_pin, 645 + void *pin_priv, 646 + const struct dpll_device *dpll, 647 + void *dpll_priv, u64 *frequency, 648 + struct netlink_ext_ack *extack) 649 + { 650 + struct zl3073x_dpll *zldpll = dpll_priv; 651 + struct zl3073x_dev *zldev = zldpll->dev; 652 + struct zl3073x_dpll_pin *pin = pin_priv; 653 + struct device *dev = zldev->dev; 654 + u8 out, signal_format, synth; 655 + u32 output_div, synth_freq; 656 + int rc; 657 + 658 + out = zl3073x_output_pin_out_get(pin->id); 659 + synth = zl3073x_out_synth_get(zldev, out); 660 + synth_freq = zl3073x_synth_freq_get(zldev, synth); 661 + 662 + guard(mutex)(&zldev->multiop_lock); 663 + 664 + /* Read output configuration into mailbox */ 665 + rc = zl3073x_mb_op(zldev, ZL_REG_OUTPUT_MB_SEM, ZL_OUTPUT_MB_SEM_RD, 666 + ZL_REG_OUTPUT_MB_MASK, BIT(out)); 667 + if (rc) 668 + return rc; 669 + 670 + rc = zl3073x_read_u32(zldev, ZL_REG_OUTPUT_DIV, &output_div); 671 + if (rc) 672 + return rc; 673 + 674 + /* Check output divisor for zero */ 675 + if (!output_div) { 676 + dev_err(dev, "Zero divisor for output %u got from device\n", 677 + out); 678 + return -EINVAL; 679 + } 680 + 681 + /* Read used signal format for the given output */ 682 + signal_format = zl3073x_out_signal_format_get(zldev, out); 683 + 684 + switch (signal_format) { 685 + case ZL_OUTPUT_MODE_SIGNAL_FORMAT_2_NDIV: 686 + case ZL_OUTPUT_MODE_SIGNAL_FORMAT_2_NDIV_INV: 687 + /* In case of divided format we have to distiguish between 688 + * given output pin type. 689 + */ 690 + if (zl3073x_dpll_is_p_pin(pin)) { 691 + /* For P-pin the resulting frequency is computed as 692 + * simple division of synth frequency and output 693 + * divisor. 694 + */ 695 + *frequency = synth_freq / output_div; 696 + } else { 697 + /* For N-pin we have to divide additionally by 698 + * divisor stored in esync_period output mailbox 699 + * register that is used as N-pin divisor for these 700 + * modes. 701 + */ 702 + u32 ndiv; 703 + 704 + rc = zl3073x_read_u32(zldev, ZL_REG_OUTPUT_ESYNC_PERIOD, 705 + &ndiv); 706 + if (rc) 707 + return rc; 708 + 709 + /* Check N-pin divisor for zero */ 710 + if (!ndiv) { 711 + dev_err(dev, 712 + "Zero N-pin divisor for output %u got from device\n", 713 + out); 714 + return -EINVAL; 715 + } 716 + 717 + /* Compute final divisor for N-pin */ 718 + *frequency = synth_freq / output_div / ndiv; 719 + } 720 + break; 721 + default: 722 + /* In other modes the resulting frequency is computed as 723 + * division of synth frequency and output divisor. 724 + */ 725 + *frequency = synth_freq / output_div; 726 + break; 727 + } 728 + 729 + return rc; 730 + } 731 + 732 + static int 733 + zl3073x_dpll_output_pin_frequency_set(const struct dpll_pin *dpll_pin, 734 + void *pin_priv, 735 + const struct dpll_device *dpll, 736 + void *dpll_priv, u64 frequency, 737 + struct netlink_ext_ack *extack) 738 + { 739 + struct zl3073x_dpll *zldpll = dpll_priv; 740 + struct zl3073x_dev *zldev = zldpll->dev; 741 + struct zl3073x_dpll_pin *pin = pin_priv; 742 + struct device *dev = zldev->dev; 743 + u32 output_n_freq, output_p_freq; 744 + u8 out, signal_format, synth; 745 + u32 cur_div, new_div, ndiv; 746 + u32 synth_freq; 747 + int rc; 748 + 749 + out = zl3073x_output_pin_out_get(pin->id); 750 + synth = zl3073x_out_synth_get(zldev, out); 751 + synth_freq = zl3073x_synth_freq_get(zldev, synth); 752 + new_div = synth_freq / (u32)frequency; 753 + 754 + /* Get used signal format for the given output */ 755 + signal_format = zl3073x_out_signal_format_get(zldev, out); 756 + 757 + guard(mutex)(&zldev->multiop_lock); 758 + 759 + /* Load output configuration */ 760 + rc = zl3073x_mb_op(zldev, ZL_REG_OUTPUT_MB_SEM, ZL_OUTPUT_MB_SEM_RD, 761 + ZL_REG_OUTPUT_MB_MASK, BIT(out)); 762 + if (rc) 763 + return rc; 764 + 765 + /* Check signal format */ 766 + if (signal_format != ZL_OUTPUT_MODE_SIGNAL_FORMAT_2_NDIV && 767 + signal_format != ZL_OUTPUT_MODE_SIGNAL_FORMAT_2_NDIV_INV) { 768 + /* For non N-divided signal formats the frequency is computed 769 + * as division of synth frequency and output divisor. 770 + */ 771 + rc = zl3073x_write_u32(zldev, ZL_REG_OUTPUT_DIV, new_div); 772 + if (rc) 773 + return rc; 774 + 775 + /* For 50/50 duty cycle the divisor is equal to width */ 776 + rc = zl3073x_write_u32(zldev, ZL_REG_OUTPUT_WIDTH, new_div); 777 + if (rc) 778 + return rc; 779 + 780 + /* Commit output configuration */ 781 + return zl3073x_mb_op(zldev, 782 + ZL_REG_OUTPUT_MB_SEM, ZL_OUTPUT_MB_SEM_WR, 783 + ZL_REG_OUTPUT_MB_MASK, BIT(out)); 784 + } 785 + 786 + /* For N-divided signal format get current divisor */ 787 + rc = zl3073x_read_u32(zldev, ZL_REG_OUTPUT_DIV, &cur_div); 788 + if (rc) 789 + return rc; 790 + 791 + /* Check output divisor for zero */ 792 + if (!cur_div) { 793 + dev_err(dev, "Zero divisor for output %u got from device\n", 794 + out); 795 + return -EINVAL; 796 + } 797 + 798 + /* Get N-pin divisor (shares the same register with esync */ 799 + rc = zl3073x_read_u32(zldev, ZL_REG_OUTPUT_ESYNC_PERIOD, &ndiv); 800 + if (rc) 801 + return rc; 802 + 803 + /* Check N-pin divisor for zero */ 804 + if (!ndiv) { 805 + dev_err(dev, 806 + "Zero N-pin divisor for output %u got from device\n", 807 + out); 808 + return -EINVAL; 809 + } 810 + 811 + /* Compute current output frequency for P-pin */ 812 + output_p_freq = synth_freq / cur_div; 813 + 814 + /* Compute current N-pin frequency */ 815 + output_n_freq = output_p_freq / ndiv; 816 + 817 + if (zl3073x_dpll_is_p_pin(pin)) { 818 + /* We are going to change output frequency for P-pin but 819 + * if the requested frequency is less than current N-pin 820 + * frequency then indicate a failure as we are not able 821 + * to compute N-pin divisor to keep its frequency unchanged. 822 + */ 823 + if (frequency <= output_n_freq) 824 + return -EINVAL; 825 + 826 + /* Update the output divisor */ 827 + rc = zl3073x_write_u32(zldev, ZL_REG_OUTPUT_DIV, new_div); 828 + if (rc) 829 + return rc; 830 + 831 + /* For 50/50 duty cycle the divisor is equal to width */ 832 + rc = zl3073x_write_u32(zldev, ZL_REG_OUTPUT_WIDTH, new_div); 833 + if (rc) 834 + return rc; 835 + 836 + /* Compute new divisor for N-pin */ 837 + ndiv = (u32)frequency / output_n_freq; 838 + } else { 839 + /* We are going to change frequency of N-pin but if 840 + * the requested freq is greater or equal than freq of P-pin 841 + * in the output pair we cannot compute divisor for the N-pin. 842 + * In this case indicate a failure. 843 + */ 844 + if (output_p_freq <= frequency) 845 + return -EINVAL; 846 + 847 + /* Compute new divisor for N-pin */ 848 + ndiv = output_p_freq / (u32)frequency; 849 + } 850 + 851 + /* Update divisor for the N-pin */ 852 + rc = zl3073x_write_u32(zldev, ZL_REG_OUTPUT_ESYNC_PERIOD, ndiv); 853 + if (rc) 854 + return rc; 855 + 856 + /* For 50/50 duty cycle the divisor is equal to width */ 857 + rc = zl3073x_write_u32(zldev, ZL_REG_OUTPUT_ESYNC_WIDTH, ndiv); 858 + if (rc) 859 + return rc; 860 + 861 + /* Commit output configuration */ 862 + return zl3073x_mb_op(zldev, ZL_REG_OUTPUT_MB_SEM, ZL_OUTPUT_MB_SEM_WR, 863 + ZL_REG_OUTPUT_MB_MASK, BIT(out)); 864 + } 865 + 866 + static int 867 + zl3073x_dpll_output_pin_state_on_dpll_get(const struct dpll_pin *dpll_pin, 868 + void *pin_priv, 869 + const struct dpll_device *dpll, 870 + void *dpll_priv, 871 + enum dpll_pin_state *state, 872 + struct netlink_ext_ack *extack) 873 + { 874 + /* If the output pin is registered then it is always connected */ 875 + *state = DPLL_PIN_STATE_CONNECTED; 876 + 877 + return 0; 878 + } 879 + 880 + static int 881 + zl3073x_dpll_lock_status_get(const struct dpll_device *dpll, void *dpll_priv, 882 + enum dpll_lock_status *status, 883 + enum dpll_lock_status_error *status_error, 884 + struct netlink_ext_ack *extack) 885 + { 886 + struct zl3073x_dpll *zldpll = dpll_priv; 887 + struct zl3073x_dev *zldev = zldpll->dev; 888 + u8 mon_status, state; 889 + int rc; 890 + 891 + switch (zldpll->refsel_mode) { 892 + case ZL_DPLL_MODE_REFSEL_MODE_FREERUN: 893 + case ZL_DPLL_MODE_REFSEL_MODE_NCO: 894 + /* In FREERUN and NCO modes the DPLL is always unlocked */ 895 + *status = DPLL_LOCK_STATUS_UNLOCKED; 896 + 897 + return 0; 898 + default: 899 + break; 900 + } 901 + 902 + /* Read DPLL monitor status */ 903 + rc = zl3073x_read_u8(zldev, ZL_REG_DPLL_MON_STATUS(zldpll->id), 904 + &mon_status); 905 + if (rc) 906 + return rc; 907 + state = FIELD_GET(ZL_DPLL_MON_STATUS_STATE, mon_status); 908 + 909 + switch (state) { 910 + case ZL_DPLL_MON_STATUS_STATE_LOCK: 911 + if (FIELD_GET(ZL_DPLL_MON_STATUS_HO_READY, mon_status)) 912 + *status = DPLL_LOCK_STATUS_LOCKED_HO_ACQ; 913 + else 914 + *status = DPLL_LOCK_STATUS_LOCKED; 915 + break; 916 + case ZL_DPLL_MON_STATUS_STATE_HOLDOVER: 917 + case ZL_DPLL_MON_STATUS_STATE_ACQUIRING: 918 + *status = DPLL_LOCK_STATUS_HOLDOVER; 919 + break; 920 + default: 921 + dev_warn(zldev->dev, "Unknown DPLL monitor status: 0x%02x\n", 922 + mon_status); 923 + *status = DPLL_LOCK_STATUS_UNLOCKED; 924 + break; 925 + } 926 + 927 + return 0; 928 + } 929 + 930 + static int 931 + zl3073x_dpll_mode_get(const struct dpll_device *dpll, void *dpll_priv, 932 + enum dpll_mode *mode, struct netlink_ext_ack *extack) 933 + { 934 + struct zl3073x_dpll *zldpll = dpll_priv; 935 + 936 + switch (zldpll->refsel_mode) { 937 + case ZL_DPLL_MODE_REFSEL_MODE_FREERUN: 938 + case ZL_DPLL_MODE_REFSEL_MODE_HOLDOVER: 939 + case ZL_DPLL_MODE_REFSEL_MODE_NCO: 940 + case ZL_DPLL_MODE_REFSEL_MODE_REFLOCK: 941 + /* Use MANUAL for device FREERUN, HOLDOVER, NCO and 942 + * REFLOCK modes 943 + */ 944 + *mode = DPLL_MODE_MANUAL; 945 + break; 946 + case ZL_DPLL_MODE_REFSEL_MODE_AUTO: 947 + /* Use AUTO for device AUTO mode */ 948 + *mode = DPLL_MODE_AUTOMATIC; 949 + break; 950 + default: 951 + return -EINVAL; 952 + } 953 + 954 + return 0; 955 + } 956 + 957 + static const struct dpll_pin_ops zl3073x_dpll_input_pin_ops = { 958 + .direction_get = zl3073x_dpll_pin_direction_get, 959 + .frequency_get = zl3073x_dpll_input_pin_frequency_get, 960 + .frequency_set = zl3073x_dpll_input_pin_frequency_set, 961 + .prio_get = zl3073x_dpll_input_pin_prio_get, 962 + .prio_set = zl3073x_dpll_input_pin_prio_set, 963 + .state_on_dpll_get = zl3073x_dpll_input_pin_state_on_dpll_get, 964 + .state_on_dpll_set = zl3073x_dpll_input_pin_state_on_dpll_set, 965 + }; 966 + 967 + static const struct dpll_pin_ops zl3073x_dpll_output_pin_ops = { 968 + .direction_get = zl3073x_dpll_pin_direction_get, 969 + .frequency_get = zl3073x_dpll_output_pin_frequency_get, 970 + .frequency_set = zl3073x_dpll_output_pin_frequency_set, 971 + .state_on_dpll_get = zl3073x_dpll_output_pin_state_on_dpll_get, 972 + }; 973 + 974 + static const struct dpll_device_ops zl3073x_dpll_device_ops = { 975 + .lock_status_get = zl3073x_dpll_lock_status_get, 976 + .mode_get = zl3073x_dpll_mode_get, 977 + }; 978 + 979 + /** 980 + * zl3073x_dpll_pin_alloc - allocate DPLL pin 981 + * @zldpll: pointer to zl3073x_dpll 982 + * @dir: pin direction 983 + * @id: pin id 984 + * 985 + * Allocates and initializes zl3073x_dpll_pin structure for given 986 + * pin id and direction. 987 + * 988 + * Return: pointer to allocated structure on success, error pointer on error 989 + */ 990 + static struct zl3073x_dpll_pin * 991 + zl3073x_dpll_pin_alloc(struct zl3073x_dpll *zldpll, enum dpll_pin_direction dir, 992 + u8 id) 993 + { 994 + struct zl3073x_dpll_pin *pin; 995 + 996 + pin = kzalloc(sizeof(*pin), GFP_KERNEL); 997 + if (!pin) 998 + return ERR_PTR(-ENOMEM); 999 + 1000 + pin->dpll = zldpll; 1001 + pin->dir = dir; 1002 + pin->id = id; 1003 + 1004 + return pin; 1005 + } 1006 + 1007 + /** 1008 + * zl3073x_dpll_pin_free - deallocate DPLL pin 1009 + * @pin: pin to free 1010 + * 1011 + * Deallocates DPLL pin previously allocated by @zl3073x_dpll_pin_alloc. 1012 + */ 1013 + static void 1014 + zl3073x_dpll_pin_free(struct zl3073x_dpll_pin *pin) 1015 + { 1016 + WARN(pin->dpll_pin, "DPLL pin is still registered\n"); 1017 + 1018 + kfree(pin); 1019 + } 1020 + 1021 + /** 1022 + * zl3073x_dpll_pin_register - register DPLL pin 1023 + * @pin: pointer to DPLL pin 1024 + * @index: absolute pin index for registration 1025 + * 1026 + * Registers given DPLL pin into DPLL sub-system. 1027 + * 1028 + * Return: 0 on success, <0 on error 1029 + */ 1030 + static int 1031 + zl3073x_dpll_pin_register(struct zl3073x_dpll_pin *pin, u32 index) 1032 + { 1033 + struct zl3073x_dpll *zldpll = pin->dpll; 1034 + struct zl3073x_pin_props *props; 1035 + const struct dpll_pin_ops *ops; 1036 + int rc; 1037 + 1038 + /* Get pin properties */ 1039 + props = zl3073x_pin_props_get(zldpll->dev, pin->dir, pin->id); 1040 + if (IS_ERR(props)) 1041 + return PTR_ERR(props); 1042 + 1043 + /* Save package label */ 1044 + strscpy(pin->label, props->package_label); 1045 + 1046 + if (zl3073x_dpll_is_input_pin(pin)) { 1047 + rc = zl3073x_dpll_ref_prio_get(pin, &pin->prio); 1048 + if (rc) 1049 + goto err_prio_get; 1050 + 1051 + if (pin->prio == ZL_DPLL_REF_PRIO_NONE) { 1052 + /* Clamp prio to max value & mark pin non-selectable */ 1053 + pin->prio = ZL_DPLL_REF_PRIO_MAX; 1054 + pin->selectable = false; 1055 + } else { 1056 + /* Mark pin as selectable */ 1057 + pin->selectable = true; 1058 + } 1059 + } 1060 + 1061 + /* Create or get existing DPLL pin */ 1062 + pin->dpll_pin = dpll_pin_get(zldpll->dev->clock_id, index, THIS_MODULE, 1063 + &props->dpll_props); 1064 + if (IS_ERR(pin->dpll_pin)) { 1065 + rc = PTR_ERR(pin->dpll_pin); 1066 + goto err_pin_get; 1067 + } 1068 + 1069 + if (zl3073x_dpll_is_input_pin(pin)) 1070 + ops = &zl3073x_dpll_input_pin_ops; 1071 + else 1072 + ops = &zl3073x_dpll_output_pin_ops; 1073 + 1074 + /* Register the pin */ 1075 + rc = dpll_pin_register(zldpll->dpll_dev, pin->dpll_pin, ops, pin); 1076 + if (rc) 1077 + goto err_register; 1078 + 1079 + /* Free pin properties */ 1080 + zl3073x_pin_props_put(props); 1081 + 1082 + return 0; 1083 + 1084 + err_register: 1085 + dpll_pin_put(pin->dpll_pin); 1086 + err_prio_get: 1087 + pin->dpll_pin = NULL; 1088 + err_pin_get: 1089 + zl3073x_pin_props_put(props); 1090 + 1091 + return rc; 1092 + } 1093 + 1094 + /** 1095 + * zl3073x_dpll_pin_unregister - unregister DPLL pin 1096 + * @pin: pointer to DPLL pin 1097 + * 1098 + * Unregisters pin previously registered by @zl3073x_dpll_pin_register. 1099 + */ 1100 + static void 1101 + zl3073x_dpll_pin_unregister(struct zl3073x_dpll_pin *pin) 1102 + { 1103 + struct zl3073x_dpll *zldpll = pin->dpll; 1104 + const struct dpll_pin_ops *ops; 1105 + 1106 + WARN(!pin->dpll_pin, "DPLL pin is not registered\n"); 1107 + 1108 + if (zl3073x_dpll_is_input_pin(pin)) 1109 + ops = &zl3073x_dpll_input_pin_ops; 1110 + else 1111 + ops = &zl3073x_dpll_output_pin_ops; 1112 + 1113 + /* Unregister the pin */ 1114 + dpll_pin_unregister(zldpll->dpll_dev, pin->dpll_pin, ops, pin); 1115 + 1116 + dpll_pin_put(pin->dpll_pin); 1117 + pin->dpll_pin = NULL; 1118 + } 1119 + 1120 + /** 1121 + * zl3073x_dpll_pins_unregister - unregister all registered DPLL pins 1122 + * @zldpll: pointer to zl3073x_dpll structure 1123 + * 1124 + * Enumerates all DPLL pins registered to given DPLL device and 1125 + * unregisters them. 1126 + */ 1127 + static void 1128 + zl3073x_dpll_pins_unregister(struct zl3073x_dpll *zldpll) 1129 + { 1130 + struct zl3073x_dpll_pin *pin, *next; 1131 + 1132 + list_for_each_entry_safe(pin, next, &zldpll->pins, list) { 1133 + zl3073x_dpll_pin_unregister(pin); 1134 + list_del(&pin->list); 1135 + zl3073x_dpll_pin_free(pin); 1136 + } 1137 + } 1138 + 1139 + /** 1140 + * zl3073x_dpll_pin_is_registrable - check if the pin is registrable 1141 + * @zldpll: pointer to zl3073x_dpll structure 1142 + * @dir: pin direction 1143 + * @index: pin index 1144 + * 1145 + * Checks if the given pin can be registered to given DPLL. For both 1146 + * directions the pin can be registered if it is enabled. In case of 1147 + * differential signal type only P-pin is reported as registrable. 1148 + * And additionally for the output pin, the pin can be registered only 1149 + * if it is connected to synthesizer that is driven by given DPLL. 1150 + * 1151 + * Return: true if the pin is registrable, false if not 1152 + */ 1153 + static bool 1154 + zl3073x_dpll_pin_is_registrable(struct zl3073x_dpll *zldpll, 1155 + enum dpll_pin_direction dir, u8 index) 1156 + { 1157 + struct zl3073x_dev *zldev = zldpll->dev; 1158 + bool is_diff, is_enabled; 1159 + const char *name; 1160 + 1161 + if (dir == DPLL_PIN_DIRECTION_INPUT) { 1162 + u8 ref = zl3073x_input_pin_ref_get(index); 1163 + 1164 + name = "REF"; 1165 + 1166 + /* Skip the pin if the DPLL is running in NCO mode */ 1167 + if (zldpll->refsel_mode == ZL_DPLL_MODE_REFSEL_MODE_NCO) 1168 + return false; 1169 + 1170 + is_diff = zl3073x_ref_is_diff(zldev, ref); 1171 + is_enabled = zl3073x_ref_is_enabled(zldev, ref); 1172 + } else { 1173 + /* Output P&N pair shares single HW output */ 1174 + u8 out = zl3073x_output_pin_out_get(index); 1175 + 1176 + name = "OUT"; 1177 + 1178 + /* Skip the pin if it is connected to different DPLL channel */ 1179 + if (zl3073x_out_dpll_get(zldev, out) != zldpll->id) { 1180 + dev_dbg(zldev->dev, 1181 + "%s%u is driven by different DPLL\n", name, 1182 + out); 1183 + 1184 + return false; 1185 + } 1186 + 1187 + is_diff = zl3073x_out_is_diff(zldev, out); 1188 + is_enabled = zl3073x_out_is_enabled(zldev, out); 1189 + } 1190 + 1191 + /* Skip N-pin if the corresponding input/output is differential */ 1192 + if (is_diff && zl3073x_is_n_pin(index)) { 1193 + dev_dbg(zldev->dev, "%s%u is differential, skipping N-pin\n", 1194 + name, index / 2); 1195 + 1196 + return false; 1197 + } 1198 + 1199 + /* Skip the pin if it is disabled */ 1200 + if (!is_enabled) { 1201 + dev_dbg(zldev->dev, "%s%u%c is disabled\n", name, index / 2, 1202 + zl3073x_is_p_pin(index) ? 'P' : 'N'); 1203 + 1204 + return false; 1205 + } 1206 + 1207 + return true; 1208 + } 1209 + 1210 + /** 1211 + * zl3073x_dpll_pins_register - register all registerable DPLL pins 1212 + * @zldpll: pointer to zl3073x_dpll structure 1213 + * 1214 + * Enumerates all possible input/output pins and registers all of them 1215 + * that are registrable. 1216 + * 1217 + * Return: 0 on success, <0 on error 1218 + */ 1219 + static int 1220 + zl3073x_dpll_pins_register(struct zl3073x_dpll *zldpll) 1221 + { 1222 + struct zl3073x_dpll_pin *pin; 1223 + enum dpll_pin_direction dir; 1224 + u8 id, index; 1225 + int rc; 1226 + 1227 + /* Process input pins */ 1228 + for (index = 0; index < ZL3073X_NUM_PINS; index++) { 1229 + /* First input pins and then output pins */ 1230 + if (index < ZL3073X_NUM_INPUT_PINS) { 1231 + id = index; 1232 + dir = DPLL_PIN_DIRECTION_INPUT; 1233 + } else { 1234 + id = index - ZL3073X_NUM_INPUT_PINS; 1235 + dir = DPLL_PIN_DIRECTION_OUTPUT; 1236 + } 1237 + 1238 + /* Check if the pin registrable to this DPLL */ 1239 + if (!zl3073x_dpll_pin_is_registrable(zldpll, dir, id)) 1240 + continue; 1241 + 1242 + pin = zl3073x_dpll_pin_alloc(zldpll, dir, id); 1243 + if (IS_ERR(pin)) { 1244 + rc = PTR_ERR(pin); 1245 + goto error; 1246 + } 1247 + 1248 + rc = zl3073x_dpll_pin_register(pin, index); 1249 + if (rc) 1250 + goto error; 1251 + 1252 + list_add(&pin->list, &zldpll->pins); 1253 + } 1254 + 1255 + return 0; 1256 + 1257 + error: 1258 + zl3073x_dpll_pins_unregister(zldpll); 1259 + 1260 + return rc; 1261 + } 1262 + 1263 + /** 1264 + * zl3073x_dpll_device_register - register DPLL device 1265 + * @zldpll: pointer to zl3073x_dpll structure 1266 + * 1267 + * Registers given DPLL device into DPLL sub-system. 1268 + * 1269 + * Return: 0 on success, <0 on error 1270 + */ 1271 + static int 1272 + zl3073x_dpll_device_register(struct zl3073x_dpll *zldpll) 1273 + { 1274 + struct zl3073x_dev *zldev = zldpll->dev; 1275 + u8 dpll_mode_refsel; 1276 + int rc; 1277 + 1278 + /* Read DPLL mode and forcibly selected reference */ 1279 + rc = zl3073x_read_u8(zldev, ZL_REG_DPLL_MODE_REFSEL(zldpll->id), 1280 + &dpll_mode_refsel); 1281 + if (rc) 1282 + return rc; 1283 + 1284 + /* Extract mode and selected input reference */ 1285 + zldpll->refsel_mode = FIELD_GET(ZL_DPLL_MODE_REFSEL_MODE, 1286 + dpll_mode_refsel); 1287 + zldpll->forced_ref = FIELD_GET(ZL_DPLL_MODE_REFSEL_REF, 1288 + dpll_mode_refsel); 1289 + 1290 + zldpll->dpll_dev = dpll_device_get(zldev->clock_id, zldpll->id, 1291 + THIS_MODULE); 1292 + if (IS_ERR(zldpll->dpll_dev)) { 1293 + rc = PTR_ERR(zldpll->dpll_dev); 1294 + zldpll->dpll_dev = NULL; 1295 + 1296 + return rc; 1297 + } 1298 + 1299 + rc = dpll_device_register(zldpll->dpll_dev, 1300 + zl3073x_prop_dpll_type_get(zldev, zldpll->id), 1301 + &zl3073x_dpll_device_ops, zldpll); 1302 + if (rc) { 1303 + dpll_device_put(zldpll->dpll_dev); 1304 + zldpll->dpll_dev = NULL; 1305 + } 1306 + 1307 + return rc; 1308 + } 1309 + 1310 + /** 1311 + * zl3073x_dpll_device_unregister - unregister DPLL device 1312 + * @zldpll: pointer to zl3073x_dpll structure 1313 + * 1314 + * Unregisters given DPLL device from DPLL sub-system previously registered 1315 + * by @zl3073x_dpll_device_register. 1316 + */ 1317 + static void 1318 + zl3073x_dpll_device_unregister(struct zl3073x_dpll *zldpll) 1319 + { 1320 + WARN(!zldpll->dpll_dev, "DPLL device is not registered\n"); 1321 + 1322 + dpll_device_unregister(zldpll->dpll_dev, &zl3073x_dpll_device_ops, 1323 + zldpll); 1324 + dpll_device_put(zldpll->dpll_dev); 1325 + zldpll->dpll_dev = NULL; 1326 + } 1327 + 1328 + /** 1329 + * zl3073x_dpll_changes_check - check for changes and send notifications 1330 + * @zldpll: pointer to zl3073x_dpll structure 1331 + * 1332 + * Checks for changes on given DPLL device and its registered DPLL pins 1333 + * and sends notifications about them. 1334 + * 1335 + * This function is periodically called from @zl3073x_dev_periodic_work. 1336 + */ 1337 + void 1338 + zl3073x_dpll_changes_check(struct zl3073x_dpll *zldpll) 1339 + { 1340 + struct zl3073x_dev *zldev = zldpll->dev; 1341 + enum dpll_lock_status lock_status; 1342 + struct device *dev = zldev->dev; 1343 + struct zl3073x_dpll_pin *pin; 1344 + int rc; 1345 + 1346 + /* Get current lock status for the DPLL */ 1347 + rc = zl3073x_dpll_lock_status_get(zldpll->dpll_dev, zldpll, 1348 + &lock_status, NULL, NULL); 1349 + if (rc) { 1350 + dev_err(dev, "Failed to get DPLL%u lock status: %pe\n", 1351 + zldpll->id, ERR_PTR(rc)); 1352 + return; 1353 + } 1354 + 1355 + /* If lock status was changed then notify DPLL core */ 1356 + if (zldpll->lock_status != lock_status) { 1357 + zldpll->lock_status = lock_status; 1358 + dpll_device_change_ntf(zldpll->dpll_dev); 1359 + } 1360 + 1361 + /* Input pin monitoring does make sense only in automatic 1362 + * or forced reference modes. 1363 + */ 1364 + if (zldpll->refsel_mode != ZL_DPLL_MODE_REFSEL_MODE_AUTO && 1365 + zldpll->refsel_mode != ZL_DPLL_MODE_REFSEL_MODE_REFLOCK) 1366 + return; 1367 + 1368 + list_for_each_entry(pin, &zldpll->pins, list) { 1369 + enum dpll_pin_state state; 1370 + 1371 + /* Output pins change checks are not necessary because output 1372 + * states are constant. 1373 + */ 1374 + if (!zl3073x_dpll_is_input_pin(pin)) 1375 + continue; 1376 + 1377 + rc = zl3073x_dpll_ref_state_get(pin, &state); 1378 + if (rc) { 1379 + dev_err(dev, 1380 + "Failed to get %s on DPLL%u state: %pe\n", 1381 + pin->label, zldpll->id, ERR_PTR(rc)); 1382 + return; 1383 + } 1384 + 1385 + if (state != pin->pin_state) { 1386 + dev_dbg(dev, "%s state changed: %u->%u\n", pin->label, 1387 + pin->pin_state, state); 1388 + pin->pin_state = state; 1389 + dpll_pin_change_ntf(pin->dpll_pin); 1390 + } 1391 + } 1392 + } 1393 + 1394 + /** 1395 + * zl3073x_dpll_init_fine_phase_adjust - do initial fine phase adjustments 1396 + * @zldev: pointer to zl3073x device 1397 + * 1398 + * Performs initial fine phase adjustments needed per datasheet. 1399 + * 1400 + * Return: 0 on success, <0 on error 1401 + */ 1402 + int 1403 + zl3073x_dpll_init_fine_phase_adjust(struct zl3073x_dev *zldev) 1404 + { 1405 + int rc; 1406 + 1407 + rc = zl3073x_write_u8(zldev, ZL_REG_SYNTH_PHASE_SHIFT_MASK, 0x1f); 1408 + if (rc) 1409 + return rc; 1410 + 1411 + rc = zl3073x_write_u8(zldev, ZL_REG_SYNTH_PHASE_SHIFT_INTVL, 0x01); 1412 + if (rc) 1413 + return rc; 1414 + 1415 + rc = zl3073x_write_u16(zldev, ZL_REG_SYNTH_PHASE_SHIFT_DATA, 0xffff); 1416 + if (rc) 1417 + return rc; 1418 + 1419 + rc = zl3073x_write_u8(zldev, ZL_REG_SYNTH_PHASE_SHIFT_CTRL, 0x01); 1420 + if (rc) 1421 + return rc; 1422 + 1423 + return rc; 1424 + } 1425 + 1426 + /** 1427 + * zl3073x_dpll_alloc - allocate DPLL device 1428 + * @zldev: pointer to zl3073x device 1429 + * @ch: DPLL channel number 1430 + * 1431 + * Allocates DPLL device structure for given DPLL channel. 1432 + * 1433 + * Return: pointer to DPLL device on success, error pointer on error 1434 + */ 1435 + struct zl3073x_dpll * 1436 + zl3073x_dpll_alloc(struct zl3073x_dev *zldev, u8 ch) 1437 + { 1438 + struct zl3073x_dpll *zldpll; 1439 + 1440 + zldpll = kzalloc(sizeof(*zldpll), GFP_KERNEL); 1441 + if (!zldpll) 1442 + return ERR_PTR(-ENOMEM); 1443 + 1444 + zldpll->dev = zldev; 1445 + zldpll->id = ch; 1446 + INIT_LIST_HEAD(&zldpll->pins); 1447 + 1448 + return zldpll; 1449 + } 1450 + 1451 + /** 1452 + * zl3073x_dpll_free - free DPLL device 1453 + * @zldpll: pointer to zl3073x_dpll structure 1454 + * 1455 + * Deallocates given DPLL device previously allocated by @zl3073x_dpll_alloc. 1456 + */ 1457 + void 1458 + zl3073x_dpll_free(struct zl3073x_dpll *zldpll) 1459 + { 1460 + WARN(zldpll->dpll_dev, "DPLL device is still registered\n"); 1461 + 1462 + kfree(zldpll); 1463 + } 1464 + 1465 + /** 1466 + * zl3073x_dpll_register - register DPLL device and all its pins 1467 + * @zldpll: pointer to zl3073x_dpll structure 1468 + * 1469 + * Registers given DPLL device and all its pins into DPLL sub-system. 1470 + * 1471 + * Return: 0 on success, <0 on error 1472 + */ 1473 + int 1474 + zl3073x_dpll_register(struct zl3073x_dpll *zldpll) 1475 + { 1476 + int rc; 1477 + 1478 + rc = zl3073x_dpll_device_register(zldpll); 1479 + if (rc) 1480 + return rc; 1481 + 1482 + rc = zl3073x_dpll_pins_register(zldpll); 1483 + if (rc) { 1484 + zl3073x_dpll_device_unregister(zldpll); 1485 + return rc; 1486 + } 1487 + 1488 + return 0; 1489 + } 1490 + 1491 + /** 1492 + * zl3073x_dpll_unregister - unregister DPLL device and its pins 1493 + * @zldpll: pointer to zl3073x_dpll structure 1494 + * 1495 + * Unregisters given DPLL device and all its pins from DPLL sub-system 1496 + * previously registered by @zl3073x_dpll_register. 1497 + */ 1498 + void 1499 + zl3073x_dpll_unregister(struct zl3073x_dpll *zldpll) 1500 + { 1501 + /* Unregister all pins and dpll */ 1502 + zl3073x_dpll_pins_unregister(zldpll); 1503 + zl3073x_dpll_device_unregister(zldpll); 1504 + }
+42
drivers/dpll/zl3073x/dpll.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + 3 + #ifndef _ZL3073X_DPLL_H 4 + #define _ZL3073X_DPLL_H 5 + 6 + #include <linux/dpll.h> 7 + #include <linux/list.h> 8 + 9 + #include "core.h" 10 + 11 + /** 12 + * struct zl3073x_dpll - ZL3073x DPLL sub-device structure 13 + * @list: this DPLL list entry 14 + * @dev: pointer to multi-function parent device 15 + * @id: DPLL index 16 + * @refsel_mode: reference selection mode 17 + * @forced_ref: selected reference in forced reference lock mode 18 + * @dpll_dev: pointer to registered DPLL device 19 + * @lock_status: last saved DPLL lock status 20 + * @pins: list of pins 21 + */ 22 + struct zl3073x_dpll { 23 + struct list_head list; 24 + struct zl3073x_dev *dev; 25 + u8 id; 26 + u8 refsel_mode; 27 + u8 forced_ref; 28 + struct dpll_device *dpll_dev; 29 + enum dpll_lock_status lock_status; 30 + struct list_head pins; 31 + }; 32 + 33 + struct zl3073x_dpll *zl3073x_dpll_alloc(struct zl3073x_dev *zldev, u8 ch); 34 + void zl3073x_dpll_free(struct zl3073x_dpll *zldpll); 35 + 36 + int zl3073x_dpll_register(struct zl3073x_dpll *zldpll); 37 + void zl3073x_dpll_unregister(struct zl3073x_dpll *zldpll); 38 + 39 + int zl3073x_dpll_init_fine_phase_adjust(struct zl3073x_dev *zldev); 40 + void zl3073x_dpll_changes_check(struct zl3073x_dpll *zldpll); 41 + 42 + #endif /* _ZL3073X_DPLL_H */
+76
drivers/dpll/zl3073x/i2c.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + 3 + #include <linux/dev_printk.h> 4 + #include <linux/err.h> 5 + #include <linux/i2c.h> 6 + #include <linux/module.h> 7 + #include <linux/regmap.h> 8 + 9 + #include "core.h" 10 + 11 + static int zl3073x_i2c_probe(struct i2c_client *client) 12 + { 13 + struct device *dev = &client->dev; 14 + struct zl3073x_dev *zldev; 15 + 16 + zldev = zl3073x_devm_alloc(dev); 17 + if (IS_ERR(zldev)) 18 + return PTR_ERR(zldev); 19 + 20 + zldev->regmap = devm_regmap_init_i2c(client, &zl3073x_regmap_config); 21 + if (IS_ERR(zldev->regmap)) 22 + return dev_err_probe(dev, PTR_ERR(zldev->regmap), 23 + "Failed to initialize regmap\n"); 24 + 25 + return zl3073x_dev_probe(zldev, i2c_get_match_data(client)); 26 + } 27 + 28 + static const struct i2c_device_id zl3073x_i2c_id[] = { 29 + { 30 + .name = "zl30731", 31 + .driver_data = (kernel_ulong_t)&zl30731_chip_info, 32 + }, 33 + { 34 + .name = "zl30732", 35 + .driver_data = (kernel_ulong_t)&zl30732_chip_info, 36 + }, 37 + { 38 + .name = "zl30733", 39 + .driver_data = (kernel_ulong_t)&zl30733_chip_info, 40 + }, 41 + { 42 + .name = "zl30734", 43 + .driver_data = (kernel_ulong_t)&zl30734_chip_info, 44 + }, 45 + { 46 + .name = "zl30735", 47 + .driver_data = (kernel_ulong_t)&zl30735_chip_info, 48 + }, 49 + { /* sentinel */ } 50 + }; 51 + MODULE_DEVICE_TABLE(i2c, zl3073x_i2c_id); 52 + 53 + static const struct of_device_id zl3073x_i2c_of_match[] = { 54 + { .compatible = "microchip,zl30731", .data = &zl30731_chip_info }, 55 + { .compatible = "microchip,zl30732", .data = &zl30732_chip_info }, 56 + { .compatible = "microchip,zl30733", .data = &zl30733_chip_info }, 57 + { .compatible = "microchip,zl30734", .data = &zl30734_chip_info }, 58 + { .compatible = "microchip,zl30735", .data = &zl30735_chip_info }, 59 + { /* sentinel */ } 60 + }; 61 + MODULE_DEVICE_TABLE(of, zl3073x_i2c_of_match); 62 + 63 + static struct i2c_driver zl3073x_i2c_driver = { 64 + .driver = { 65 + .name = "zl3073x-i2c", 66 + .of_match_table = zl3073x_i2c_of_match, 67 + }, 68 + .probe = zl3073x_i2c_probe, 69 + .id_table = zl3073x_i2c_id, 70 + }; 71 + module_i2c_driver(zl3073x_i2c_driver); 72 + 73 + MODULE_AUTHOR("Ivan Vecera <ivecera@redhat.com>"); 74 + MODULE_DESCRIPTION("Microchip ZL3073x I2C driver"); 75 + MODULE_IMPORT_NS("ZL3073X"); 76 + MODULE_LICENSE("GPL");
+358
drivers/dpll/zl3073x/prop.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + 3 + #include <linux/array_size.h> 4 + #include <linux/dev_printk.h> 5 + #include <linux/err.h> 6 + #include <linux/errno.h> 7 + #include <linux/fwnode.h> 8 + #include <linux/property.h> 9 + #include <linux/slab.h> 10 + #include <linux/string.h> 11 + 12 + #include "core.h" 13 + #include "prop.h" 14 + 15 + /** 16 + * zl3073x_pin_check_freq - verify frequency for given pin 17 + * @zldev: pointer to zl3073x device 18 + * @dir: pin direction 19 + * @id: pin index 20 + * @freq: frequency to check 21 + * 22 + * The function checks the given frequency is valid for the device. For input 23 + * pins it checks that the frequency can be factorized using supported base 24 + * frequencies. For output pins it checks that the frequency divides connected 25 + * synth frequency without remainder. 26 + * 27 + * Return: true if the frequency is valid, false if not. 28 + */ 29 + static bool 30 + zl3073x_pin_check_freq(struct zl3073x_dev *zldev, enum dpll_pin_direction dir, 31 + u8 id, u64 freq) 32 + { 33 + if (freq > U32_MAX) 34 + goto err_inv_freq; 35 + 36 + if (dir == DPLL_PIN_DIRECTION_INPUT) { 37 + int rc; 38 + 39 + /* Check if the frequency can be factorized */ 40 + rc = zl3073x_ref_freq_factorize(freq, NULL, NULL); 41 + if (rc) 42 + goto err_inv_freq; 43 + } else { 44 + u32 synth_freq; 45 + u8 out, synth; 46 + 47 + /* Get output pin synthesizer */ 48 + out = zl3073x_output_pin_out_get(id); 49 + synth = zl3073x_out_synth_get(zldev, out); 50 + 51 + /* Get synth frequency */ 52 + synth_freq = zl3073x_synth_freq_get(zldev, synth); 53 + 54 + /* Check the frequency divides synth frequency */ 55 + if (synth_freq % (u32)freq) 56 + goto err_inv_freq; 57 + } 58 + 59 + return true; 60 + 61 + err_inv_freq: 62 + dev_warn(zldev->dev, 63 + "Unsupported frequency %llu Hz in firmware node\n", freq); 64 + 65 + return false; 66 + } 67 + 68 + /** 69 + * zl3073x_prop_pin_package_label_set - get package label for the pin 70 + * @zldev: pointer to zl3073x device 71 + * @props: pointer to pin properties 72 + * @dir: pin direction 73 + * @id: pin index 74 + * 75 + * Generates package label string and stores it into pin properties structure. 76 + * 77 + * Possible formats: 78 + * REF<n> - differential input reference 79 + * REF<n>P & REF<n>N - single-ended input reference (P or N pin) 80 + * OUT<n> - differential output 81 + * OUT<n>P & OUT<n>N - single-ended output (P or N pin) 82 + */ 83 + static void 84 + zl3073x_prop_pin_package_label_set(struct zl3073x_dev *zldev, 85 + struct zl3073x_pin_props *props, 86 + enum dpll_pin_direction dir, u8 id) 87 + { 88 + const char *prefix, *suffix; 89 + bool is_diff; 90 + 91 + if (dir == DPLL_PIN_DIRECTION_INPUT) { 92 + u8 ref; 93 + 94 + prefix = "REF"; 95 + ref = zl3073x_input_pin_ref_get(id); 96 + is_diff = zl3073x_ref_is_diff(zldev, ref); 97 + } else { 98 + u8 out; 99 + 100 + prefix = "OUT"; 101 + out = zl3073x_output_pin_out_get(id); 102 + is_diff = zl3073x_out_is_diff(zldev, out); 103 + } 104 + 105 + if (!is_diff) 106 + suffix = zl3073x_is_p_pin(id) ? "P" : "N"; 107 + else 108 + suffix = ""; /* No suffix for differential one */ 109 + 110 + snprintf(props->package_label, sizeof(props->package_label), "%s%u%s", 111 + prefix, id / 2, suffix); 112 + 113 + /* Set package_label pointer in DPLL core properties to generated 114 + * string. 115 + */ 116 + props->dpll_props.package_label = props->package_label; 117 + } 118 + 119 + /** 120 + * zl3073x_prop_pin_fwnode_get - get fwnode for given pin 121 + * @zldev: pointer to zl3073x device 122 + * @props: pointer to pin properties 123 + * @dir: pin direction 124 + * @id: pin index 125 + * 126 + * Return: 0 on success, -ENOENT if the firmware node does not exist 127 + */ 128 + static int 129 + zl3073x_prop_pin_fwnode_get(struct zl3073x_dev *zldev, 130 + struct zl3073x_pin_props *props, 131 + enum dpll_pin_direction dir, u8 id) 132 + { 133 + struct fwnode_handle *pins_node, *pin_node; 134 + const char *node_name; 135 + 136 + if (dir == DPLL_PIN_DIRECTION_INPUT) 137 + node_name = "input-pins"; 138 + else 139 + node_name = "output-pins"; 140 + 141 + /* Get node containing input or output pins */ 142 + pins_node = device_get_named_child_node(zldev->dev, node_name); 143 + if (!pins_node) { 144 + dev_dbg(zldev->dev, "'%s' sub-node is missing\n", node_name); 145 + return -ENOENT; 146 + } 147 + 148 + /* Enumerate child pin nodes and find the requested one */ 149 + fwnode_for_each_child_node(pins_node, pin_node) { 150 + u32 reg; 151 + 152 + if (fwnode_property_read_u32(pin_node, "reg", &reg)) 153 + continue; 154 + 155 + if (id == reg) 156 + break; 157 + } 158 + 159 + /* Release pin parent node */ 160 + fwnode_handle_put(pins_node); 161 + 162 + /* Save found node */ 163 + props->fwnode = pin_node; 164 + 165 + dev_dbg(zldev->dev, "Firmware node for %s %sfound\n", 166 + props->package_label, pin_node ? "" : "NOT "); 167 + 168 + return pin_node ? 0 : -ENOENT; 169 + } 170 + 171 + /** 172 + * zl3073x_pin_props_get - get pin properties 173 + * @zldev: pointer to zl3073x device 174 + * @dir: pin direction 175 + * @index: pin index 176 + * 177 + * The function looks for firmware node for the given pin if it is provided 178 + * by the system firmware (DT or ACPI), allocates pin properties structure, 179 + * generates package label string according pin type and optionally fetches 180 + * board label, connection type, supported frequencies and esync capability 181 + * from the firmware node if it does exist. 182 + * 183 + * Pointer that is returned by this function should be freed using 184 + * @zl3073x_pin_props_put(). 185 + * 186 + * Return: 187 + * * pointer to allocated pin properties structure on success 188 + * * error pointer in case of error 189 + */ 190 + struct zl3073x_pin_props *zl3073x_pin_props_get(struct zl3073x_dev *zldev, 191 + enum dpll_pin_direction dir, 192 + u8 index) 193 + { 194 + struct dpll_pin_frequency *ranges; 195 + struct zl3073x_pin_props *props; 196 + int i, j, num_freqs, rc; 197 + const char *type; 198 + u64 *freqs; 199 + 200 + props = kzalloc(sizeof(*props), GFP_KERNEL); 201 + if (!props) 202 + return ERR_PTR(-ENOMEM); 203 + 204 + /* Set default pin type and capabilities */ 205 + if (dir == DPLL_PIN_DIRECTION_INPUT) { 206 + props->dpll_props.type = DPLL_PIN_TYPE_EXT; 207 + props->dpll_props.capabilities = 208 + DPLL_PIN_CAPABILITIES_PRIORITY_CAN_CHANGE | 209 + DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE; 210 + } else { 211 + props->dpll_props.type = DPLL_PIN_TYPE_GNSS; 212 + } 213 + 214 + props->dpll_props.phase_range.min = S32_MIN; 215 + props->dpll_props.phase_range.max = S32_MAX; 216 + 217 + zl3073x_prop_pin_package_label_set(zldev, props, dir, index); 218 + 219 + /* Get firmware node for the given pin */ 220 + rc = zl3073x_prop_pin_fwnode_get(zldev, props, dir, index); 221 + if (rc) 222 + return props; /* Return if it does not exist */ 223 + 224 + /* Look for label property and store the value as board label */ 225 + fwnode_property_read_string(props->fwnode, "label", 226 + &props->dpll_props.board_label); 227 + 228 + /* Look for pin type property and translate its value to DPLL 229 + * pin type enum if it is present. 230 + */ 231 + if (!fwnode_property_read_string(props->fwnode, "connection-type", 232 + &type)) { 233 + if (!strcmp(type, "ext")) 234 + props->dpll_props.type = DPLL_PIN_TYPE_EXT; 235 + else if (!strcmp(type, "gnss")) 236 + props->dpll_props.type = DPLL_PIN_TYPE_GNSS; 237 + else if (!strcmp(type, "int")) 238 + props->dpll_props.type = DPLL_PIN_TYPE_INT_OSCILLATOR; 239 + else if (!strcmp(type, "synce")) 240 + props->dpll_props.type = DPLL_PIN_TYPE_SYNCE_ETH_PORT; 241 + else 242 + dev_warn(zldev->dev, 243 + "Unknown or unsupported pin type '%s'\n", 244 + type); 245 + } 246 + 247 + /* Check if the pin supports embedded sync control */ 248 + props->esync_control = fwnode_property_read_bool(props->fwnode, 249 + "esync-control"); 250 + 251 + /* Read supported frequencies property if it is specified */ 252 + num_freqs = fwnode_property_count_u64(props->fwnode, 253 + "supported-frequencies-hz"); 254 + if (num_freqs <= 0) 255 + /* Return if the property does not exist or number is 0 */ 256 + return props; 257 + 258 + /* The firmware node specifies list of supported frequencies while 259 + * DPLL core pin properties requires list of frequency ranges. 260 + * So read the frequency list into temporary array. 261 + */ 262 + freqs = kcalloc(num_freqs, sizeof(*freqs), GFP_KERNEL); 263 + if (!freqs) { 264 + rc = -ENOMEM; 265 + goto err_alloc_freqs; 266 + } 267 + 268 + /* Read frequencies list from firmware node */ 269 + fwnode_property_read_u64_array(props->fwnode, 270 + "supported-frequencies-hz", freqs, 271 + num_freqs); 272 + 273 + /* Allocate frequency ranges list and fill it */ 274 + ranges = kcalloc(num_freqs, sizeof(*ranges), GFP_KERNEL); 275 + if (!ranges) { 276 + rc = -ENOMEM; 277 + goto err_alloc_ranges; 278 + } 279 + 280 + /* Convert list of frequencies to list of frequency ranges but 281 + * filter-out frequencies that are not representable by device 282 + */ 283 + for (i = 0, j = 0; i < num_freqs; i++) { 284 + struct dpll_pin_frequency freq = DPLL_PIN_FREQUENCY(freqs[i]); 285 + 286 + if (zl3073x_pin_check_freq(zldev, dir, index, freqs[i])) { 287 + ranges[j] = freq; 288 + j++; 289 + } 290 + } 291 + 292 + /* Save number of freq ranges and pointer to them into pin properties */ 293 + props->dpll_props.freq_supported = ranges; 294 + props->dpll_props.freq_supported_num = j; 295 + 296 + /* Free temporary array */ 297 + kfree(freqs); 298 + 299 + return props; 300 + 301 + err_alloc_ranges: 302 + kfree(freqs); 303 + err_alloc_freqs: 304 + fwnode_handle_put(props->fwnode); 305 + kfree(props); 306 + 307 + return ERR_PTR(rc); 308 + } 309 + 310 + /** 311 + * zl3073x_pin_props_put - release pin properties 312 + * @props: pin properties to free 313 + * 314 + * The function deallocates given pin properties structure. 315 + */ 316 + void zl3073x_pin_props_put(struct zl3073x_pin_props *props) 317 + { 318 + /* Free supported frequency ranges list if it is present */ 319 + kfree(props->dpll_props.freq_supported); 320 + 321 + /* Put firmware handle if it is present */ 322 + if (props->fwnode) 323 + fwnode_handle_put(props->fwnode); 324 + 325 + kfree(props); 326 + } 327 + 328 + /** 329 + * zl3073x_prop_dpll_type_get - get DPLL channel type 330 + * @zldev: pointer to zl3073x device 331 + * @index: DPLL channel index 332 + * 333 + * Return: DPLL type for given DPLL channel 334 + */ 335 + enum dpll_type 336 + zl3073x_prop_dpll_type_get(struct zl3073x_dev *zldev, u8 index) 337 + { 338 + const char *types[ZL3073X_MAX_CHANNELS]; 339 + int count; 340 + 341 + /* Read dpll types property from firmware */ 342 + count = device_property_read_string_array(zldev->dev, "dpll-types", 343 + types, ARRAY_SIZE(types)); 344 + 345 + /* Return default if property or entry for given channel is missing */ 346 + if (index >= count) 347 + return DPLL_TYPE_PPS; 348 + 349 + if (!strcmp(types[index], "pps")) 350 + return DPLL_TYPE_PPS; 351 + else if (!strcmp(types[index], "eec")) 352 + return DPLL_TYPE_EEC; 353 + 354 + dev_info(zldev->dev, "Unknown DPLL type '%s', using default\n", 355 + types[index]); 356 + 357 + return DPLL_TYPE_PPS; /* Default */ 358 + }
+34
drivers/dpll/zl3073x/prop.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + 3 + #ifndef _ZL3073X_PROP_H 4 + #define _ZL3073X_PROP_H 5 + 6 + #include <linux/dpll.h> 7 + 8 + #include "core.h" 9 + 10 + struct fwnode_handle; 11 + 12 + /** 13 + * struct zl3073x_pin_props - pin properties 14 + * @fwnode: pin firmware node 15 + * @dpll_props: DPLL core pin properties 16 + * @package_label: pin package label 17 + * @esync_control: embedded sync support 18 + */ 19 + struct zl3073x_pin_props { 20 + struct fwnode_handle *fwnode; 21 + struct dpll_pin_properties dpll_props; 22 + char package_label[8]; 23 + bool esync_control; 24 + }; 25 + 26 + enum dpll_type zl3073x_prop_dpll_type_get(struct zl3073x_dev *zldev, u8 index); 27 + 28 + struct zl3073x_pin_props *zl3073x_pin_props_get(struct zl3073x_dev *zldev, 29 + enum dpll_pin_direction dir, 30 + u8 index); 31 + 32 + void zl3073x_pin_props_put(struct zl3073x_pin_props *props); 33 + 34 + #endif /* _ZL3073X_PROP_H */
+208
drivers/dpll/zl3073x/regs.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + 3 + #ifndef _ZL3073X_REGS_H 4 + #define _ZL3073X_REGS_H 5 + 6 + #include <linux/bitfield.h> 7 + #include <linux/bits.h> 8 + 9 + /* 10 + * Register address structure: 11 + * =========================== 12 + * 25 19 18 16 15 7 6 0 13 + * +------------------------------------------+ 14 + * | max_offset | size | page | page_offset | 15 + * +------------------------------------------+ 16 + * 17 + * page_offset ... <0x00..0x7F> 18 + * page .......... HW page number 19 + * size .......... register byte size (1, 2, 4 or 6) 20 + * max_offset .... maximal offset for indexed registers 21 + * (for non-indexed regs max_offset == page_offset) 22 + */ 23 + 24 + #define ZL_REG_OFFSET_MASK GENMASK(6, 0) 25 + #define ZL_REG_PAGE_MASK GENMASK(15, 7) 26 + #define ZL_REG_SIZE_MASK GENMASK(18, 16) 27 + #define ZL_REG_MAX_OFFSET_MASK GENMASK(25, 19) 28 + #define ZL_REG_ADDR_MASK GENMASK(15, 0) 29 + 30 + #define ZL_REG_OFFSET(_reg) FIELD_GET(ZL_REG_OFFSET_MASK, _reg) 31 + #define ZL_REG_PAGE(_reg) FIELD_GET(ZL_REG_PAGE_MASK, _reg) 32 + #define ZL_REG_MAX_OFFSET(_reg) FIELD_GET(ZL_REG_MAX_OFFSET_MASK, _reg) 33 + #define ZL_REG_SIZE(_reg) FIELD_GET(ZL_REG_SIZE_MASK, _reg) 34 + #define ZL_REG_ADDR(_reg) FIELD_GET(ZL_REG_ADDR_MASK, _reg) 35 + 36 + /** 37 + * ZL_REG_IDX - define indexed register 38 + * @_idx: index of register to access 39 + * @_page: register page 40 + * @_offset: register offset in page 41 + * @_size: register byte size (1, 2, 4 or 6) 42 + * @_items: number of register indices 43 + * @_stride: stride between items in bytes 44 + * 45 + * All parameters except @_idx should be constant. 46 + */ 47 + #define ZL_REG_IDX(_idx, _page, _offset, _size, _items, _stride) \ 48 + (FIELD_PREP(ZL_REG_OFFSET_MASK, \ 49 + (_offset) + (_idx) * (_stride)) | \ 50 + FIELD_PREP_CONST(ZL_REG_PAGE_MASK, _page) | \ 51 + FIELD_PREP_CONST(ZL_REG_SIZE_MASK, _size) | \ 52 + FIELD_PREP_CONST(ZL_REG_MAX_OFFSET_MASK, \ 53 + (_offset) + ((_items) - 1) * (_stride))) 54 + 55 + /** 56 + * ZL_REG - define simple (non-indexed) register 57 + * @_page: register page 58 + * @_offset: register offset in page 59 + * @_size: register byte size (1, 2, 4 or 6) 60 + * 61 + * All parameters should be constant. 62 + */ 63 + #define ZL_REG(_page, _offset, _size) \ 64 + ZL_REG_IDX(0, _page, _offset, _size, 1, 0) 65 + 66 + /************************** 67 + * Register Page 0, General 68 + **************************/ 69 + 70 + #define ZL_REG_ID ZL_REG(0, 0x01, 2) 71 + #define ZL_REG_REVISION ZL_REG(0, 0x03, 2) 72 + #define ZL_REG_FW_VER ZL_REG(0, 0x05, 2) 73 + #define ZL_REG_CUSTOM_CONFIG_VER ZL_REG(0, 0x07, 4) 74 + 75 + /************************* 76 + * Register Page 2, Status 77 + *************************/ 78 + 79 + #define ZL_REG_REF_MON_STATUS(_idx) \ 80 + ZL_REG_IDX(_idx, 2, 0x02, 1, ZL3073X_NUM_REFS, 1) 81 + #define ZL_REF_MON_STATUS_OK 0 /* all bits zeroed */ 82 + 83 + #define ZL_REG_DPLL_MON_STATUS(_idx) \ 84 + ZL_REG_IDX(_idx, 2, 0x10, 1, ZL3073X_MAX_CHANNELS, 1) 85 + #define ZL_DPLL_MON_STATUS_STATE GENMASK(1, 0) 86 + #define ZL_DPLL_MON_STATUS_STATE_ACQUIRING 0 87 + #define ZL_DPLL_MON_STATUS_STATE_LOCK 1 88 + #define ZL_DPLL_MON_STATUS_STATE_HOLDOVER 2 89 + #define ZL_DPLL_MON_STATUS_HO_READY BIT(2) 90 + 91 + #define ZL_REG_DPLL_REFSEL_STATUS(_idx) \ 92 + ZL_REG_IDX(_idx, 2, 0x30, 1, ZL3073X_MAX_CHANNELS, 1) 93 + #define ZL_DPLL_REFSEL_STATUS_REFSEL GENMASK(3, 0) 94 + #define ZL_DPLL_REFSEL_STATUS_STATE GENMASK(6, 4) 95 + #define ZL_DPLL_REFSEL_STATUS_STATE_LOCK 4 96 + 97 + /*********************** 98 + * Register Page 5, DPLL 99 + ***********************/ 100 + 101 + #define ZL_REG_DPLL_MODE_REFSEL(_idx) \ 102 + ZL_REG_IDX(_idx, 5, 0x04, 1, ZL3073X_MAX_CHANNELS, 4) 103 + #define ZL_DPLL_MODE_REFSEL_MODE GENMASK(2, 0) 104 + #define ZL_DPLL_MODE_REFSEL_MODE_FREERUN 0 105 + #define ZL_DPLL_MODE_REFSEL_MODE_HOLDOVER 1 106 + #define ZL_DPLL_MODE_REFSEL_MODE_REFLOCK 2 107 + #define ZL_DPLL_MODE_REFSEL_MODE_AUTO 3 108 + #define ZL_DPLL_MODE_REFSEL_MODE_NCO 4 109 + #define ZL_DPLL_MODE_REFSEL_REF GENMASK(7, 4) 110 + 111 + /*********************************** 112 + * Register Page 9, Synth and Output 113 + ***********************************/ 114 + 115 + #define ZL_REG_SYNTH_CTRL(_idx) \ 116 + ZL_REG_IDX(_idx, 9, 0x00, 1, ZL3073X_NUM_SYNTHS, 1) 117 + #define ZL_SYNTH_CTRL_EN BIT(0) 118 + #define ZL_SYNTH_CTRL_DPLL_SEL GENMASK(6, 4) 119 + 120 + #define ZL_REG_SYNTH_PHASE_SHIFT_CTRL ZL_REG(9, 0x1e, 1) 121 + #define ZL_REG_SYNTH_PHASE_SHIFT_MASK ZL_REG(9, 0x1f, 1) 122 + #define ZL_REG_SYNTH_PHASE_SHIFT_INTVL ZL_REG(9, 0x20, 1) 123 + #define ZL_REG_SYNTH_PHASE_SHIFT_DATA ZL_REG(9, 0x21, 2) 124 + 125 + #define ZL_REG_OUTPUT_CTRL(_idx) \ 126 + ZL_REG_IDX(_idx, 9, 0x28, 1, ZL3073X_NUM_OUTS, 1) 127 + #define ZL_OUTPUT_CTRL_EN BIT(0) 128 + #define ZL_OUTPUT_CTRL_SYNTH_SEL GENMASK(6, 4) 129 + 130 + /******************************* 131 + * Register Page 10, Ref Mailbox 132 + *******************************/ 133 + 134 + #define ZL_REG_REF_MB_MASK ZL_REG(10, 0x02, 2) 135 + 136 + #define ZL_REG_REF_MB_SEM ZL_REG(10, 0x04, 1) 137 + #define ZL_REF_MB_SEM_WR BIT(0) 138 + #define ZL_REF_MB_SEM_RD BIT(1) 139 + 140 + #define ZL_REG_REF_FREQ_BASE ZL_REG(10, 0x05, 2) 141 + #define ZL_REG_REF_FREQ_MULT ZL_REG(10, 0x07, 2) 142 + #define ZL_REG_REF_RATIO_M ZL_REG(10, 0x09, 2) 143 + #define ZL_REG_REF_RATIO_N ZL_REG(10, 0x0b, 2) 144 + 145 + #define ZL_REG_REF_CONFIG ZL_REG(10, 0x0d, 1) 146 + #define ZL_REF_CONFIG_ENABLE BIT(0) 147 + #define ZL_REF_CONFIG_DIFF_EN BIT(2) 148 + 149 + /******************************** 150 + * Register Page 12, DPLL Mailbox 151 + ********************************/ 152 + 153 + #define ZL_REG_DPLL_MB_MASK ZL_REG(12, 0x02, 2) 154 + 155 + #define ZL_REG_DPLL_MB_SEM ZL_REG(12, 0x04, 1) 156 + #define ZL_DPLL_MB_SEM_WR BIT(0) 157 + #define ZL_DPLL_MB_SEM_RD BIT(1) 158 + 159 + #define ZL_REG_DPLL_REF_PRIO(_idx) \ 160 + ZL_REG_IDX(_idx, 12, 0x52, 1, ZL3073X_NUM_REFS / 2, 1) 161 + #define ZL_DPLL_REF_PRIO_REF_P GENMASK(3, 0) 162 + #define ZL_DPLL_REF_PRIO_REF_N GENMASK(7, 4) 163 + #define ZL_DPLL_REF_PRIO_MAX 14 164 + #define ZL_DPLL_REF_PRIO_NONE 15 165 + 166 + /********************************* 167 + * Register Page 13, Synth Mailbox 168 + *********************************/ 169 + 170 + #define ZL_REG_SYNTH_MB_MASK ZL_REG(13, 0x02, 2) 171 + 172 + #define ZL_REG_SYNTH_MB_SEM ZL_REG(13, 0x04, 1) 173 + #define ZL_SYNTH_MB_SEM_WR BIT(0) 174 + #define ZL_SYNTH_MB_SEM_RD BIT(1) 175 + 176 + #define ZL_REG_SYNTH_FREQ_BASE ZL_REG(13, 0x06, 2) 177 + #define ZL_REG_SYNTH_FREQ_MULT ZL_REG(13, 0x08, 4) 178 + #define ZL_REG_SYNTH_FREQ_M ZL_REG(13, 0x0c, 2) 179 + #define ZL_REG_SYNTH_FREQ_N ZL_REG(13, 0x0e, 2) 180 + 181 + /********************************** 182 + * Register Page 14, Output Mailbox 183 + **********************************/ 184 + #define ZL_REG_OUTPUT_MB_MASK ZL_REG(14, 0x02, 2) 185 + 186 + #define ZL_REG_OUTPUT_MB_SEM ZL_REG(14, 0x04, 1) 187 + #define ZL_OUTPUT_MB_SEM_WR BIT(0) 188 + #define ZL_OUTPUT_MB_SEM_RD BIT(1) 189 + 190 + #define ZL_REG_OUTPUT_MODE ZL_REG(14, 0x05, 1) 191 + #define ZL_OUTPUT_MODE_SIGNAL_FORMAT GENMASK(7, 4) 192 + #define ZL_OUTPUT_MODE_SIGNAL_FORMAT_DISABLED 0 193 + #define ZL_OUTPUT_MODE_SIGNAL_FORMAT_LVDS 1 194 + #define ZL_OUTPUT_MODE_SIGNAL_FORMAT_DIFF 2 195 + #define ZL_OUTPUT_MODE_SIGNAL_FORMAT_LOWVCM 3 196 + #define ZL_OUTPUT_MODE_SIGNAL_FORMAT_2 4 197 + #define ZL_OUTPUT_MODE_SIGNAL_FORMAT_1P 5 198 + #define ZL_OUTPUT_MODE_SIGNAL_FORMAT_1N 6 199 + #define ZL_OUTPUT_MODE_SIGNAL_FORMAT_2_INV 7 200 + #define ZL_OUTPUT_MODE_SIGNAL_FORMAT_2_NDIV 12 201 + #define ZL_OUTPUT_MODE_SIGNAL_FORMAT_2_NDIV_INV 15 202 + 203 + #define ZL_REG_OUTPUT_DIV ZL_REG(14, 0x0c, 4) 204 + #define ZL_REG_OUTPUT_WIDTH ZL_REG(14, 0x10, 4) 205 + #define ZL_REG_OUTPUT_ESYNC_PERIOD ZL_REG(14, 0x14, 4) 206 + #define ZL_REG_OUTPUT_ESYNC_WIDTH ZL_REG(14, 0x18, 4) 207 + 208 + #endif /* _ZL3073X_REGS_H */
+76
drivers/dpll/zl3073x/spi.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + 3 + #include <linux/dev_printk.h> 4 + #include <linux/err.h> 5 + #include <linux/module.h> 6 + #include <linux/regmap.h> 7 + #include <linux/spi/spi.h> 8 + 9 + #include "core.h" 10 + 11 + static int zl3073x_spi_probe(struct spi_device *spi) 12 + { 13 + struct device *dev = &spi->dev; 14 + struct zl3073x_dev *zldev; 15 + 16 + zldev = zl3073x_devm_alloc(dev); 17 + if (IS_ERR(zldev)) 18 + return PTR_ERR(zldev); 19 + 20 + zldev->regmap = devm_regmap_init_spi(spi, &zl3073x_regmap_config); 21 + if (IS_ERR(zldev->regmap)) 22 + return dev_err_probe(dev, PTR_ERR(zldev->regmap), 23 + "Failed to initialize regmap\n"); 24 + 25 + return zl3073x_dev_probe(zldev, spi_get_device_match_data(spi)); 26 + } 27 + 28 + static const struct spi_device_id zl3073x_spi_id[] = { 29 + { 30 + .name = "zl30731", 31 + .driver_data = (kernel_ulong_t)&zl30731_chip_info 32 + }, 33 + { 34 + .name = "zl30732", 35 + .driver_data = (kernel_ulong_t)&zl30732_chip_info, 36 + }, 37 + { 38 + .name = "zl30733", 39 + .driver_data = (kernel_ulong_t)&zl30733_chip_info, 40 + }, 41 + { 42 + .name = "zl30734", 43 + .driver_data = (kernel_ulong_t)&zl30734_chip_info, 44 + }, 45 + { 46 + .name = "zl30735", 47 + .driver_data = (kernel_ulong_t)&zl30735_chip_info, 48 + }, 49 + { /* sentinel */ } 50 + }; 51 + MODULE_DEVICE_TABLE(spi, zl3073x_spi_id); 52 + 53 + static const struct of_device_id zl3073x_spi_of_match[] = { 54 + { .compatible = "microchip,zl30731", .data = &zl30731_chip_info }, 55 + { .compatible = "microchip,zl30732", .data = &zl30732_chip_info }, 56 + { .compatible = "microchip,zl30733", .data = &zl30733_chip_info }, 57 + { .compatible = "microchip,zl30734", .data = &zl30734_chip_info }, 58 + { .compatible = "microchip,zl30735", .data = &zl30735_chip_info }, 59 + { /* sentinel */ } 60 + }; 61 + MODULE_DEVICE_TABLE(of, zl3073x_spi_of_match); 62 + 63 + static struct spi_driver zl3073x_spi_driver = { 64 + .driver = { 65 + .name = "zl3073x-spi", 66 + .of_match_table = zl3073x_spi_of_match, 67 + }, 68 + .probe = zl3073x_spi_probe, 69 + .id_table = zl3073x_spi_id, 70 + }; 71 + module_spi_driver(zl3073x_spi_driver); 72 + 73 + MODULE_AUTHOR("Ivan Vecera <ivecera@redhat.com>"); 74 + MODULE_DESCRIPTION("Microchip ZL3073x SPI driver"); 75 + MODULE_IMPORT_NS("ZL3073X"); 76 + MODULE_LICENSE("GPL");
+6
include/net/devlink.h
··· 425 425 DEVLINK_PARAM_TYPE_U8 = DEVLINK_VAR_ATTR_TYPE_U8, 426 426 DEVLINK_PARAM_TYPE_U16 = DEVLINK_VAR_ATTR_TYPE_U16, 427 427 DEVLINK_PARAM_TYPE_U32 = DEVLINK_VAR_ATTR_TYPE_U32, 428 + DEVLINK_PARAM_TYPE_U64 = DEVLINK_VAR_ATTR_TYPE_U64, 428 429 DEVLINK_PARAM_TYPE_STRING = DEVLINK_VAR_ATTR_TYPE_STRING, 429 430 DEVLINK_PARAM_TYPE_BOOL = DEVLINK_VAR_ATTR_TYPE_FLAG, 430 431 }; ··· 434 433 u8 vu8; 435 434 u16 vu16; 436 435 u32 vu32; 436 + u64 vu64; 437 437 char vstr[__DEVLINK_PARAM_MAX_STRING_VALUE]; 438 438 bool vbool; 439 439 }; ··· 525 523 DEVLINK_PARAM_GENERIC_ID_IO_EQ_SIZE, 526 524 DEVLINK_PARAM_GENERIC_ID_EVENT_EQ_SIZE, 527 525 DEVLINK_PARAM_GENERIC_ID_ENABLE_PHC, 526 + DEVLINK_PARAM_GENERIC_ID_CLOCK_ID, 528 527 529 528 /* add new param generic ids above here*/ 530 529 __DEVLINK_PARAM_GENERIC_ID_MAX, ··· 586 583 587 584 #define DEVLINK_PARAM_GENERIC_ENABLE_PHC_NAME "enable_phc" 588 585 #define DEVLINK_PARAM_GENERIC_ENABLE_PHC_TYPE DEVLINK_PARAM_TYPE_BOOL 586 + 587 + #define DEVLINK_PARAM_GENERIC_CLOCK_ID_NAME "clock_id" 588 + #define DEVLINK_PARAM_GENERIC_CLOCK_ID_TYPE DEVLINK_PARAM_TYPE_U64 589 589 590 590 #define DEVLINK_PARAM_GENERIC(_id, _cmodes, _get, _set, _validate) \ 591 591 { \
+15
net/devlink/param.c
··· 97 97 .name = DEVLINK_PARAM_GENERIC_ENABLE_PHC_NAME, 98 98 .type = DEVLINK_PARAM_GENERIC_ENABLE_PHC_TYPE, 99 99 }, 100 + { 101 + .id = DEVLINK_PARAM_GENERIC_ID_CLOCK_ID, 102 + .name = DEVLINK_PARAM_GENERIC_CLOCK_ID_NAME, 103 + .type = DEVLINK_PARAM_GENERIC_CLOCK_ID_TYPE, 104 + }, 100 105 }; 101 106 102 107 static int devlink_param_generic_verify(const struct devlink_param *param) ··· 203 198 break; 204 199 case DEVLINK_PARAM_TYPE_U32: 205 200 if (nla_put_u32(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu32)) 201 + goto value_nest_cancel; 202 + break; 203 + case DEVLINK_PARAM_TYPE_U64: 204 + if (devlink_nl_put_u64(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, 205 + val.vu64)) 206 206 goto value_nest_cancel; 207 207 break; 208 208 case DEVLINK_PARAM_TYPE_STRING: ··· 443 433 if (nla_len(param_data) != sizeof(u32)) 444 434 return -EINVAL; 445 435 value->vu32 = nla_get_u32(param_data); 436 + break; 437 + case DEVLINK_PARAM_TYPE_U64: 438 + if (nla_len(param_data) != sizeof(u64)) 439 + return -EINVAL; 440 + value->vu64 = nla_get_u64(param_data); 446 441 break; 447 442 case DEVLINK_PARAM_TYPE_STRING: 448 443 len = strnlen(nla_data(param_data), nla_len(param_data));