xref: /linux/drivers/dpll/zl3073x/core.c (revision 8be4d31cb8aaeea27bde4b7ddb26e28a89062ebf)
12df8e64eSIvan Vecera // SPDX-License-Identifier: GPL-2.0-only
22df8e64eSIvan Vecera 
32df8e64eSIvan Vecera #include <linux/array_size.h>
42df8e64eSIvan Vecera #include <linux/bitfield.h>
52df8e64eSIvan Vecera #include <linux/bits.h>
62df8e64eSIvan Vecera #include <linux/dev_printk.h>
72df8e64eSIvan Vecera #include <linux/device.h>
82df8e64eSIvan Vecera #include <linux/export.h>
9b7d907d1SIvan Vecera #include <linux/math64.h>
102df8e64eSIvan Vecera #include <linux/module.h>
112df8e64eSIvan Vecera #include <linux/netlink.h>
122df8e64eSIvan Vecera #include <linux/regmap.h>
132df8e64eSIvan Vecera #include <linux/sprintf.h>
14b7d907d1SIvan Vecera #include <linux/string_choices.h>
152df8e64eSIvan Vecera #include <linux/unaligned.h>
162df8e64eSIvan Vecera #include <net/devlink.h>
172df8e64eSIvan Vecera 
182df8e64eSIvan Vecera #include "core.h"
192df8e64eSIvan Vecera #include "devlink.h"
2075a71eccSIvan Vecera #include "dpll.h"
212df8e64eSIvan Vecera #include "regs.h"
222df8e64eSIvan Vecera 
232df8e64eSIvan Vecera /* Chip IDs for zl30731 */
242df8e64eSIvan Vecera static const u16 zl30731_ids[] = {
252df8e64eSIvan Vecera 	0x0E93,
262df8e64eSIvan Vecera 	0x1E93,
272df8e64eSIvan Vecera 	0x2E93,
282df8e64eSIvan Vecera };
292df8e64eSIvan Vecera 
302df8e64eSIvan Vecera const struct zl3073x_chip_info zl30731_chip_info = {
312df8e64eSIvan Vecera 	.ids = zl30731_ids,
322df8e64eSIvan Vecera 	.num_ids = ARRAY_SIZE(zl30731_ids),
332df8e64eSIvan Vecera 	.num_channels = 1,
342df8e64eSIvan Vecera };
352df8e64eSIvan Vecera EXPORT_SYMBOL_NS_GPL(zl30731_chip_info, "ZL3073X");
362df8e64eSIvan Vecera 
372df8e64eSIvan Vecera /* Chip IDs for zl30732 */
382df8e64eSIvan Vecera static const u16 zl30732_ids[] = {
392df8e64eSIvan Vecera 	0x0E30,
402df8e64eSIvan Vecera 	0x0E94,
412df8e64eSIvan Vecera 	0x1E94,
422df8e64eSIvan Vecera 	0x1F60,
432df8e64eSIvan Vecera 	0x2E94,
442df8e64eSIvan Vecera 	0x3FC4,
452df8e64eSIvan Vecera };
462df8e64eSIvan Vecera 
472df8e64eSIvan Vecera const struct zl3073x_chip_info zl30732_chip_info = {
482df8e64eSIvan Vecera 	.ids = zl30732_ids,
492df8e64eSIvan Vecera 	.num_ids = ARRAY_SIZE(zl30732_ids),
502df8e64eSIvan Vecera 	.num_channels = 2,
512df8e64eSIvan Vecera };
522df8e64eSIvan Vecera EXPORT_SYMBOL_NS_GPL(zl30732_chip_info, "ZL3073X");
532df8e64eSIvan Vecera 
542df8e64eSIvan Vecera /* Chip IDs for zl30733 */
552df8e64eSIvan Vecera static const u16 zl30733_ids[] = {
562df8e64eSIvan Vecera 	0x0E95,
572df8e64eSIvan Vecera 	0x1E95,
582df8e64eSIvan Vecera 	0x2E95,
592df8e64eSIvan Vecera };
602df8e64eSIvan Vecera 
612df8e64eSIvan Vecera const struct zl3073x_chip_info zl30733_chip_info = {
622df8e64eSIvan Vecera 	.ids = zl30733_ids,
632df8e64eSIvan Vecera 	.num_ids = ARRAY_SIZE(zl30733_ids),
642df8e64eSIvan Vecera 	.num_channels = 3,
652df8e64eSIvan Vecera };
662df8e64eSIvan Vecera EXPORT_SYMBOL_NS_GPL(zl30733_chip_info, "ZL3073X");
672df8e64eSIvan Vecera 
682df8e64eSIvan Vecera /* Chip IDs for zl30734 */
692df8e64eSIvan Vecera static const u16 zl30734_ids[] = {
702df8e64eSIvan Vecera 	0x0E96,
712df8e64eSIvan Vecera 	0x1E96,
722df8e64eSIvan Vecera 	0x2E96,
732df8e64eSIvan Vecera };
742df8e64eSIvan Vecera 
752df8e64eSIvan Vecera const struct zl3073x_chip_info zl30734_chip_info = {
762df8e64eSIvan Vecera 	.ids = zl30734_ids,
772df8e64eSIvan Vecera 	.num_ids = ARRAY_SIZE(zl30734_ids),
782df8e64eSIvan Vecera 	.num_channels = 4,
792df8e64eSIvan Vecera };
802df8e64eSIvan Vecera EXPORT_SYMBOL_NS_GPL(zl30734_chip_info, "ZL3073X");
812df8e64eSIvan Vecera 
822df8e64eSIvan Vecera /* Chip IDs for zl30735 */
832df8e64eSIvan Vecera static const u16 zl30735_ids[] = {
842df8e64eSIvan Vecera 	0x0E97,
852df8e64eSIvan Vecera 	0x1E97,
862df8e64eSIvan Vecera 	0x2E97,
872df8e64eSIvan Vecera };
882df8e64eSIvan Vecera 
892df8e64eSIvan Vecera const struct zl3073x_chip_info zl30735_chip_info = {
902df8e64eSIvan Vecera 	.ids = zl30735_ids,
912df8e64eSIvan Vecera 	.num_ids = ARRAY_SIZE(zl30735_ids),
922df8e64eSIvan Vecera 	.num_channels = 5,
932df8e64eSIvan Vecera };
942df8e64eSIvan Vecera EXPORT_SYMBOL_NS_GPL(zl30735_chip_info, "ZL3073X");
952df8e64eSIvan Vecera 
962df8e64eSIvan Vecera #define ZL_RANGE_OFFSET		0x80
972df8e64eSIvan Vecera #define ZL_PAGE_SIZE		0x80
982df8e64eSIvan Vecera #define ZL_NUM_PAGES		15
992df8e64eSIvan Vecera #define ZL_PAGE_SEL		0x7F
1002df8e64eSIvan Vecera #define ZL_PAGE_SEL_MASK	GENMASK(3, 0)
1012df8e64eSIvan Vecera #define ZL_NUM_REGS		(ZL_NUM_PAGES * ZL_PAGE_SIZE)
1022df8e64eSIvan Vecera 
1032df8e64eSIvan Vecera /* Regmap range configuration */
1042df8e64eSIvan Vecera static const struct regmap_range_cfg zl3073x_regmap_range = {
1052df8e64eSIvan Vecera 	.range_min	= ZL_RANGE_OFFSET,
1062df8e64eSIvan Vecera 	.range_max	= ZL_RANGE_OFFSET + ZL_NUM_REGS - 1,
1072df8e64eSIvan Vecera 	.selector_reg	= ZL_PAGE_SEL,
1082df8e64eSIvan Vecera 	.selector_mask	= ZL_PAGE_SEL_MASK,
1092df8e64eSIvan Vecera 	.selector_shift	= 0,
1102df8e64eSIvan Vecera 	.window_start	= 0,
1112df8e64eSIvan Vecera 	.window_len	= ZL_PAGE_SIZE,
1122df8e64eSIvan Vecera };
1132df8e64eSIvan Vecera 
1142df8e64eSIvan Vecera static bool
zl3073x_is_volatile_reg(struct device * dev __maybe_unused,unsigned int reg)1152df8e64eSIvan Vecera zl3073x_is_volatile_reg(struct device *dev __maybe_unused, unsigned int reg)
1162df8e64eSIvan Vecera {
1172df8e64eSIvan Vecera 	/* Only page selector is non-volatile */
1182df8e64eSIvan Vecera 	return reg != ZL_PAGE_SEL;
1192df8e64eSIvan Vecera }
1202df8e64eSIvan Vecera 
1212df8e64eSIvan Vecera const struct regmap_config zl3073x_regmap_config = {
1222df8e64eSIvan Vecera 	.reg_bits	= 8,
1232df8e64eSIvan Vecera 	.val_bits	= 8,
1242df8e64eSIvan Vecera 	.max_register	= ZL_RANGE_OFFSET + ZL_NUM_REGS - 1,
1252df8e64eSIvan Vecera 	.ranges		= &zl3073x_regmap_range,
1262df8e64eSIvan Vecera 	.num_ranges	= 1,
1272df8e64eSIvan Vecera 	.cache_type	= REGCACHE_MAPLE,
1282df8e64eSIvan Vecera 	.volatile_reg	= zl3073x_is_volatile_reg,
1292df8e64eSIvan Vecera };
1302df8e64eSIvan Vecera EXPORT_SYMBOL_NS_GPL(zl3073x_regmap_config, "ZL3073X");
1312df8e64eSIvan Vecera 
132a99a9f0eSIvan Vecera /**
133a99a9f0eSIvan Vecera  * zl3073x_ref_freq_factorize - factorize given frequency
134a99a9f0eSIvan Vecera  * @freq: input frequency
135a99a9f0eSIvan Vecera  * @base: base frequency
136a99a9f0eSIvan Vecera  * @mult: multiplier
137a99a9f0eSIvan Vecera  *
138a99a9f0eSIvan Vecera  * Checks if the given frequency can be factorized using one of the
139a99a9f0eSIvan Vecera  * supported base frequencies. If so the base frequency and multiplier
140a99a9f0eSIvan Vecera  * are stored into appropriate parameters if they are not NULL.
141a99a9f0eSIvan Vecera  *
142a99a9f0eSIvan Vecera  * Return: 0 on success, -EINVAL if the frequency cannot be factorized
143a99a9f0eSIvan Vecera  */
144a99a9f0eSIvan Vecera int
zl3073x_ref_freq_factorize(u32 freq,u16 * base,u16 * mult)145a99a9f0eSIvan Vecera zl3073x_ref_freq_factorize(u32 freq, u16 *base, u16 *mult)
146a99a9f0eSIvan Vecera {
147a99a9f0eSIvan Vecera 	static const u16 base_freqs[] = {
148a99a9f0eSIvan Vecera 		1, 2, 4, 5, 8, 10, 16, 20, 25, 32, 40, 50, 64, 80, 100, 125,
149a99a9f0eSIvan Vecera 		128, 160, 200, 250, 256, 320, 400, 500, 625, 640, 800, 1000,
150a99a9f0eSIvan Vecera 		1250, 1280, 1600, 2000, 2500, 3125, 3200, 4000, 5000, 6250,
151a99a9f0eSIvan Vecera 		6400, 8000, 10000, 12500, 15625, 16000, 20000, 25000, 31250,
152a99a9f0eSIvan Vecera 		32000, 40000, 50000, 62500,
153a99a9f0eSIvan Vecera 	};
154a99a9f0eSIvan Vecera 	u32 div;
155a99a9f0eSIvan Vecera 	int i;
156a99a9f0eSIvan Vecera 
157a99a9f0eSIvan Vecera 	for (i = 0; i < ARRAY_SIZE(base_freqs); i++) {
158a99a9f0eSIvan Vecera 		div = freq / base_freqs[i];
159a99a9f0eSIvan Vecera 
160a99a9f0eSIvan Vecera 		if (div <= U16_MAX && (freq % base_freqs[i]) == 0) {
161a99a9f0eSIvan Vecera 			if (base)
162a99a9f0eSIvan Vecera 				*base = base_freqs[i];
163a99a9f0eSIvan Vecera 			if (mult)
164a99a9f0eSIvan Vecera 				*mult = div;
165a99a9f0eSIvan Vecera 
166a99a9f0eSIvan Vecera 			return 0;
167a99a9f0eSIvan Vecera 		}
168a99a9f0eSIvan Vecera 	}
169a99a9f0eSIvan Vecera 
170a99a9f0eSIvan Vecera 	return -EINVAL;
171a99a9f0eSIvan Vecera }
172a99a9f0eSIvan Vecera 
1732df8e64eSIvan Vecera static bool
zl3073x_check_reg(struct zl3073x_dev * zldev,unsigned int reg,size_t size)1742df8e64eSIvan Vecera zl3073x_check_reg(struct zl3073x_dev *zldev, unsigned int reg, size_t size)
1752df8e64eSIvan Vecera {
1762df8e64eSIvan Vecera 	/* Check that multiop lock is held when accessing registers
1772df8e64eSIvan Vecera 	 * from page 10 and above.
1782df8e64eSIvan Vecera 	 */
1792df8e64eSIvan Vecera 	if (ZL_REG_PAGE(reg) >= 10)
1802df8e64eSIvan Vecera 		lockdep_assert_held(&zldev->multiop_lock);
1812df8e64eSIvan Vecera 
1822df8e64eSIvan Vecera 	/* Check the index is in valid range for indexed register */
1832df8e64eSIvan Vecera 	if (ZL_REG_OFFSET(reg) > ZL_REG_MAX_OFFSET(reg)) {
1842df8e64eSIvan Vecera 		dev_err(zldev->dev, "Index out of range for reg 0x%04lx\n",
1852df8e64eSIvan Vecera 			ZL_REG_ADDR(reg));
1862df8e64eSIvan Vecera 		return false;
1872df8e64eSIvan Vecera 	}
1882df8e64eSIvan Vecera 	/* Check the requested size corresponds to register size */
1892df8e64eSIvan Vecera 	if (ZL_REG_SIZE(reg) != size) {
1902df8e64eSIvan Vecera 		dev_err(zldev->dev, "Invalid size %zu for reg 0x%04lx\n",
1912df8e64eSIvan Vecera 			size, ZL_REG_ADDR(reg));
1922df8e64eSIvan Vecera 		return false;
1932df8e64eSIvan Vecera 	}
1942df8e64eSIvan Vecera 
1952df8e64eSIvan Vecera 	return true;
1962df8e64eSIvan Vecera }
1972df8e64eSIvan Vecera 
1982df8e64eSIvan Vecera static int
zl3073x_read_reg(struct zl3073x_dev * zldev,unsigned int reg,void * val,size_t size)1992df8e64eSIvan Vecera zl3073x_read_reg(struct zl3073x_dev *zldev, unsigned int reg, void *val,
2002df8e64eSIvan Vecera 		 size_t size)
2012df8e64eSIvan Vecera {
2022df8e64eSIvan Vecera 	int rc;
2032df8e64eSIvan Vecera 
2042df8e64eSIvan Vecera 	if (!zl3073x_check_reg(zldev, reg, size))
2052df8e64eSIvan Vecera 		return -EINVAL;
2062df8e64eSIvan Vecera 
2072df8e64eSIvan Vecera 	/* Map the register address to virtual range */
2082df8e64eSIvan Vecera 	reg = ZL_REG_ADDR(reg) + ZL_RANGE_OFFSET;
2092df8e64eSIvan Vecera 
2102df8e64eSIvan Vecera 	rc = regmap_bulk_read(zldev->regmap, reg, val, size);
2112df8e64eSIvan Vecera 	if (rc) {
2122df8e64eSIvan Vecera 		dev_err(zldev->dev, "Failed to read reg 0x%04x: %pe\n", reg,
2132df8e64eSIvan Vecera 			ERR_PTR(rc));
2142df8e64eSIvan Vecera 		return rc;
2152df8e64eSIvan Vecera 	}
2162df8e64eSIvan Vecera 
2172df8e64eSIvan Vecera 	return 0;
2182df8e64eSIvan Vecera }
2192df8e64eSIvan Vecera 
2202df8e64eSIvan Vecera static int
zl3073x_write_reg(struct zl3073x_dev * zldev,unsigned int reg,const void * val,size_t size)2212df8e64eSIvan Vecera zl3073x_write_reg(struct zl3073x_dev *zldev, unsigned int reg, const void *val,
2222df8e64eSIvan Vecera 		  size_t size)
2232df8e64eSIvan Vecera {
2242df8e64eSIvan Vecera 	int rc;
2252df8e64eSIvan Vecera 
2262df8e64eSIvan Vecera 	if (!zl3073x_check_reg(zldev, reg, size))
2272df8e64eSIvan Vecera 		return -EINVAL;
2282df8e64eSIvan Vecera 
2292df8e64eSIvan Vecera 	/* Map the register address to virtual range */
2302df8e64eSIvan Vecera 	reg = ZL_REG_ADDR(reg) + ZL_RANGE_OFFSET;
2312df8e64eSIvan Vecera 
2322df8e64eSIvan Vecera 	rc = regmap_bulk_write(zldev->regmap, reg, val, size);
2332df8e64eSIvan Vecera 	if (rc) {
2342df8e64eSIvan Vecera 		dev_err(zldev->dev, "Failed to write reg 0x%04x: %pe\n", reg,
2352df8e64eSIvan Vecera 			ERR_PTR(rc));
2362df8e64eSIvan Vecera 		return rc;
2372df8e64eSIvan Vecera 	}
2382df8e64eSIvan Vecera 
2392df8e64eSIvan Vecera 	return 0;
2402df8e64eSIvan Vecera }
2412df8e64eSIvan Vecera 
2422df8e64eSIvan Vecera /**
2432df8e64eSIvan Vecera  * zl3073x_read_u8 - read value from 8bit register
2442df8e64eSIvan Vecera  * @zldev: zl3073x device pointer
2452df8e64eSIvan Vecera  * @reg: register to write to
2462df8e64eSIvan Vecera  * @val: value to write
2472df8e64eSIvan Vecera  *
2482df8e64eSIvan Vecera  * Reads value from given 8bit register.
2492df8e64eSIvan Vecera  *
2502df8e64eSIvan Vecera  * Returns: 0 on success, <0 on error
2512df8e64eSIvan Vecera  */
zl3073x_read_u8(struct zl3073x_dev * zldev,unsigned int reg,u8 * val)2522df8e64eSIvan Vecera int zl3073x_read_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 *val)
2532df8e64eSIvan Vecera {
2542df8e64eSIvan Vecera 	return zl3073x_read_reg(zldev, reg, val, sizeof(*val));
2552df8e64eSIvan Vecera }
2562df8e64eSIvan Vecera 
2572df8e64eSIvan Vecera /**
2582df8e64eSIvan Vecera  * zl3073x_write_u8 - write value to 16bit register
2592df8e64eSIvan Vecera  * @zldev: zl3073x device pointer
2602df8e64eSIvan Vecera  * @reg: register to write to
2612df8e64eSIvan Vecera  * @val: value to write
2622df8e64eSIvan Vecera  *
2632df8e64eSIvan Vecera  * Writes value into given 8bit register.
2642df8e64eSIvan Vecera  *
2652df8e64eSIvan Vecera  * Returns: 0 on success, <0 on error
2662df8e64eSIvan Vecera  */
zl3073x_write_u8(struct zl3073x_dev * zldev,unsigned int reg,u8 val)2672df8e64eSIvan Vecera int zl3073x_write_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 val)
2682df8e64eSIvan Vecera {
2692df8e64eSIvan Vecera 	return zl3073x_write_reg(zldev, reg, &val, sizeof(val));
2702df8e64eSIvan Vecera }
2712df8e64eSIvan Vecera 
2722df8e64eSIvan Vecera /**
2732df8e64eSIvan Vecera  * zl3073x_read_u16 - read value from 16bit register
2742df8e64eSIvan Vecera  * @zldev: zl3073x device pointer
2752df8e64eSIvan Vecera  * @reg: register to write to
2762df8e64eSIvan Vecera  * @val: value to write
2772df8e64eSIvan Vecera  *
2782df8e64eSIvan Vecera  * Reads value from given 16bit register.
2792df8e64eSIvan Vecera  *
2802df8e64eSIvan Vecera  * Returns: 0 on success, <0 on error
2812df8e64eSIvan Vecera  */
zl3073x_read_u16(struct zl3073x_dev * zldev,unsigned int reg,u16 * val)2822df8e64eSIvan Vecera int zl3073x_read_u16(struct zl3073x_dev *zldev, unsigned int reg, u16 *val)
2832df8e64eSIvan Vecera {
2842df8e64eSIvan Vecera 	int rc;
2852df8e64eSIvan Vecera 
2862df8e64eSIvan Vecera 	rc = zl3073x_read_reg(zldev, reg, val, sizeof(*val));
2872df8e64eSIvan Vecera 	if (!rc)
2882df8e64eSIvan Vecera 		be16_to_cpus(val);
2892df8e64eSIvan Vecera 
2902df8e64eSIvan Vecera 	return rc;
2912df8e64eSIvan Vecera }
2922df8e64eSIvan Vecera 
2932df8e64eSIvan Vecera /**
2942df8e64eSIvan Vecera  * zl3073x_write_u16 - write value to 16bit register
2952df8e64eSIvan Vecera  * @zldev: zl3073x device pointer
2962df8e64eSIvan Vecera  * @reg: register to write to
2972df8e64eSIvan Vecera  * @val: value to write
2982df8e64eSIvan Vecera  *
2992df8e64eSIvan Vecera  * Writes value into given 16bit register.
3002df8e64eSIvan Vecera  *
3012df8e64eSIvan Vecera  * Returns: 0 on success, <0 on error
3022df8e64eSIvan Vecera  */
zl3073x_write_u16(struct zl3073x_dev * zldev,unsigned int reg,u16 val)3032df8e64eSIvan Vecera int zl3073x_write_u16(struct zl3073x_dev *zldev, unsigned int reg, u16 val)
3042df8e64eSIvan Vecera {
3052df8e64eSIvan Vecera 	cpu_to_be16s(&val);
3062df8e64eSIvan Vecera 
3072df8e64eSIvan Vecera 	return zl3073x_write_reg(zldev, reg, &val, sizeof(val));
3082df8e64eSIvan Vecera }
3092df8e64eSIvan Vecera 
3102df8e64eSIvan Vecera /**
3112df8e64eSIvan Vecera  * zl3073x_read_u32 - read value from 32bit register
3122df8e64eSIvan Vecera  * @zldev: zl3073x device pointer
3132df8e64eSIvan Vecera  * @reg: register to write to
3142df8e64eSIvan Vecera  * @val: value to write
3152df8e64eSIvan Vecera  *
3162df8e64eSIvan Vecera  * Reads value from given 32bit register.
3172df8e64eSIvan Vecera  *
3182df8e64eSIvan Vecera  * Returns: 0 on success, <0 on error
3192df8e64eSIvan Vecera  */
zl3073x_read_u32(struct zl3073x_dev * zldev,unsigned int reg,u32 * val)3202df8e64eSIvan Vecera int zl3073x_read_u32(struct zl3073x_dev *zldev, unsigned int reg, u32 *val)
3212df8e64eSIvan Vecera {
3222df8e64eSIvan Vecera 	int rc;
3232df8e64eSIvan Vecera 
3242df8e64eSIvan Vecera 	rc = zl3073x_read_reg(zldev, reg, val, sizeof(*val));
3252df8e64eSIvan Vecera 	if (!rc)
3262df8e64eSIvan Vecera 		be32_to_cpus(val);
3272df8e64eSIvan Vecera 
3282df8e64eSIvan Vecera 	return rc;
3292df8e64eSIvan Vecera }
3302df8e64eSIvan Vecera 
3312df8e64eSIvan Vecera /**
3322df8e64eSIvan Vecera  * zl3073x_write_u32 - write value to 32bit register
3332df8e64eSIvan Vecera  * @zldev: zl3073x device pointer
3342df8e64eSIvan Vecera  * @reg: register to write to
3352df8e64eSIvan Vecera  * @val: value to write
3362df8e64eSIvan Vecera  *
3372df8e64eSIvan Vecera  * Writes value into given 32bit register.
3382df8e64eSIvan Vecera  *
3392df8e64eSIvan Vecera  * Returns: 0 on success, <0 on error
3402df8e64eSIvan Vecera  */
zl3073x_write_u32(struct zl3073x_dev * zldev,unsigned int reg,u32 val)3412df8e64eSIvan Vecera int zl3073x_write_u32(struct zl3073x_dev *zldev, unsigned int reg, u32 val)
3422df8e64eSIvan Vecera {
3432df8e64eSIvan Vecera 	cpu_to_be32s(&val);
3442df8e64eSIvan Vecera 
3452df8e64eSIvan Vecera 	return zl3073x_write_reg(zldev, reg, &val, sizeof(val));
3462df8e64eSIvan Vecera }
3472df8e64eSIvan Vecera 
3482df8e64eSIvan Vecera /**
3492df8e64eSIvan Vecera  * zl3073x_read_u48 - read value from 48bit register
3502df8e64eSIvan Vecera  * @zldev: zl3073x device pointer
3512df8e64eSIvan Vecera  * @reg: register to write to
3522df8e64eSIvan Vecera  * @val: value to write
3532df8e64eSIvan Vecera  *
3542df8e64eSIvan Vecera  * Reads value from given 48bit register.
3552df8e64eSIvan Vecera  *
3562df8e64eSIvan Vecera  * Returns: 0 on success, <0 on error
3572df8e64eSIvan Vecera  */
zl3073x_read_u48(struct zl3073x_dev * zldev,unsigned int reg,u64 * val)3582df8e64eSIvan Vecera int zl3073x_read_u48(struct zl3073x_dev *zldev, unsigned int reg, u64 *val)
3592df8e64eSIvan Vecera {
3602df8e64eSIvan Vecera 	u8 buf[6];
3612df8e64eSIvan Vecera 	int rc;
3622df8e64eSIvan Vecera 
3632df8e64eSIvan Vecera 	rc = zl3073x_read_reg(zldev, reg, buf, sizeof(buf));
3642df8e64eSIvan Vecera 	if (!rc)
3652df8e64eSIvan Vecera 		*val = get_unaligned_be48(buf);
3662df8e64eSIvan Vecera 
3672df8e64eSIvan Vecera 	return rc;
3682df8e64eSIvan Vecera }
3692df8e64eSIvan Vecera 
3702df8e64eSIvan Vecera /**
3712df8e64eSIvan Vecera  * zl3073x_write_u48 - write value to 48bit register
3722df8e64eSIvan Vecera  * @zldev: zl3073x device pointer
3732df8e64eSIvan Vecera  * @reg: register to write to
3742df8e64eSIvan Vecera  * @val: value to write
3752df8e64eSIvan Vecera  *
3762df8e64eSIvan Vecera  * Writes value into given 48bit register.
3772df8e64eSIvan Vecera  * The value must be from the interval -S48_MIN to U48_MAX.
3782df8e64eSIvan Vecera  *
3792df8e64eSIvan Vecera  * Returns: 0 on success, <0 on error
3802df8e64eSIvan Vecera  */
zl3073x_write_u48(struct zl3073x_dev * zldev,unsigned int reg,u64 val)3812df8e64eSIvan Vecera int zl3073x_write_u48(struct zl3073x_dev *zldev, unsigned int reg, u64 val)
3822df8e64eSIvan Vecera {
3832df8e64eSIvan Vecera 	u8 buf[6];
3842df8e64eSIvan Vecera 
3852df8e64eSIvan Vecera 	/* Check the value belongs to <S48_MIN, U48_MAX>
3862df8e64eSIvan Vecera 	 * Any value >= S48_MIN has bits 47..63 set.
3872df8e64eSIvan Vecera 	 */
3882df8e64eSIvan Vecera 	if (val > GENMASK_ULL(47, 0) && val < GENMASK_ULL(63, 47)) {
3892df8e64eSIvan Vecera 		dev_err(zldev->dev, "Value 0x%0llx out of range\n", val);
3902df8e64eSIvan Vecera 		return -EINVAL;
3912df8e64eSIvan Vecera 	}
3922df8e64eSIvan Vecera 
3932df8e64eSIvan Vecera 	put_unaligned_be48(val, buf);
3942df8e64eSIvan Vecera 
3952df8e64eSIvan Vecera 	return zl3073x_write_reg(zldev, reg, buf, sizeof(buf));
3962df8e64eSIvan Vecera }
3972df8e64eSIvan Vecera 
3982df8e64eSIvan Vecera /**
3992df8e64eSIvan Vecera  * zl3073x_poll_zero_u8 - wait for register to be cleared by device
4002df8e64eSIvan Vecera  * @zldev: zl3073x device pointer
4012df8e64eSIvan Vecera  * @reg: register to poll (has to be 8bit register)
4022df8e64eSIvan Vecera  * @mask: bit mask for polling
4032df8e64eSIvan Vecera  *
4042df8e64eSIvan Vecera  * Waits for bits specified by @mask in register @reg value to be cleared
4052df8e64eSIvan Vecera  * by the device.
4062df8e64eSIvan Vecera  *
4072df8e64eSIvan Vecera  * Returns: 0 on success, <0 on error
4082df8e64eSIvan Vecera  */
zl3073x_poll_zero_u8(struct zl3073x_dev * zldev,unsigned int reg,u8 mask)4092df8e64eSIvan Vecera int zl3073x_poll_zero_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 mask)
4102df8e64eSIvan Vecera {
4112df8e64eSIvan Vecera 	/* Register polling sleep & timeout */
4122df8e64eSIvan Vecera #define ZL_POLL_SLEEP_US   10
4132df8e64eSIvan Vecera #define ZL_POLL_TIMEOUT_US 2000000
4142df8e64eSIvan Vecera 	unsigned int val;
4152df8e64eSIvan Vecera 
4162df8e64eSIvan Vecera 	/* Check the register is 8bit */
4172df8e64eSIvan Vecera 	if (ZL_REG_SIZE(reg) != 1) {
4182df8e64eSIvan Vecera 		dev_err(zldev->dev, "Invalid reg 0x%04lx size for polling\n",
4192df8e64eSIvan Vecera 			ZL_REG_ADDR(reg));
4202df8e64eSIvan Vecera 		return -EINVAL;
4212df8e64eSIvan Vecera 	}
4222df8e64eSIvan Vecera 
4232df8e64eSIvan Vecera 	/* Map the register address to virtual range */
4242df8e64eSIvan Vecera 	reg = ZL_REG_ADDR(reg) + ZL_RANGE_OFFSET;
4252df8e64eSIvan Vecera 
4262df8e64eSIvan Vecera 	return regmap_read_poll_timeout(zldev->regmap, reg, val, !(val & mask),
4272df8e64eSIvan Vecera 					ZL_POLL_SLEEP_US, ZL_POLL_TIMEOUT_US);
4282df8e64eSIvan Vecera }
4292df8e64eSIvan Vecera 
zl3073x_mb_op(struct zl3073x_dev * zldev,unsigned int op_reg,u8 op_val,unsigned int mask_reg,u16 mask_val)430b7d907d1SIvan Vecera int zl3073x_mb_op(struct zl3073x_dev *zldev, unsigned int op_reg, u8 op_val,
431b7d907d1SIvan Vecera 		  unsigned int mask_reg, u16 mask_val)
432b7d907d1SIvan Vecera {
433b7d907d1SIvan Vecera 	int rc;
434b7d907d1SIvan Vecera 
435b7d907d1SIvan Vecera 	/* Set mask for the operation */
436b7d907d1SIvan Vecera 	rc = zl3073x_write_u16(zldev, mask_reg, mask_val);
437b7d907d1SIvan Vecera 	if (rc)
438b7d907d1SIvan Vecera 		return rc;
439b7d907d1SIvan Vecera 
440b7d907d1SIvan Vecera 	/* Trigger the operation */
441b7d907d1SIvan Vecera 	rc = zl3073x_write_u8(zldev, op_reg, op_val);
442b7d907d1SIvan Vecera 	if (rc)
443b7d907d1SIvan Vecera 		return rc;
444b7d907d1SIvan Vecera 
445b7d907d1SIvan Vecera 	/* Wait for the operation to actually finish */
446b7d907d1SIvan Vecera 	return zl3073x_poll_zero_u8(zldev, op_reg, op_val);
447b7d907d1SIvan Vecera }
448b7d907d1SIvan Vecera 
449b7d907d1SIvan Vecera /**
450b7d907d1SIvan Vecera  * zl3073x_ref_state_fetch - get input reference state
451b7d907d1SIvan Vecera  * @zldev: pointer to zl3073x_dev structure
452b7d907d1SIvan Vecera  * @index: input reference index to fetch state for
453b7d907d1SIvan Vecera  *
454b7d907d1SIvan Vecera  * Function fetches information for the given input reference that are
455b7d907d1SIvan Vecera  * invariant and stores them for later use.
456b7d907d1SIvan Vecera  *
457b7d907d1SIvan Vecera  * Return: 0 on success, <0 on error
458b7d907d1SIvan Vecera  */
459b7d907d1SIvan Vecera static int
zl3073x_ref_state_fetch(struct zl3073x_dev * zldev,u8 index)460b7d907d1SIvan Vecera zl3073x_ref_state_fetch(struct zl3073x_dev *zldev, u8 index)
461b7d907d1SIvan Vecera {
462b7d907d1SIvan Vecera 	struct zl3073x_ref *input = &zldev->ref[index];
463b7d907d1SIvan Vecera 	u8 ref_config;
464b7d907d1SIvan Vecera 	int rc;
465b7d907d1SIvan Vecera 
466b7d907d1SIvan Vecera 	/* If the input is differential then the configuration for N-pin
467b7d907d1SIvan Vecera 	 * reference is ignored and P-pin config is used for both.
468b7d907d1SIvan Vecera 	 */
469b7d907d1SIvan Vecera 	if (zl3073x_is_n_pin(index) &&
470b7d907d1SIvan Vecera 	    zl3073x_ref_is_diff(zldev, index - 1)) {
471b7d907d1SIvan Vecera 		input->enabled = zl3073x_ref_is_enabled(zldev, index - 1);
472b7d907d1SIvan Vecera 		input->diff = true;
473b7d907d1SIvan Vecera 
474b7d907d1SIvan Vecera 		return 0;
475b7d907d1SIvan Vecera 	}
476b7d907d1SIvan Vecera 
477b7d907d1SIvan Vecera 	guard(mutex)(&zldev->multiop_lock);
478b7d907d1SIvan Vecera 
479b7d907d1SIvan Vecera 	/* Read reference configuration */
480b7d907d1SIvan Vecera 	rc = zl3073x_mb_op(zldev, ZL_REG_REF_MB_SEM, ZL_REF_MB_SEM_RD,
481b7d907d1SIvan Vecera 			   ZL_REG_REF_MB_MASK, BIT(index));
482b7d907d1SIvan Vecera 	if (rc)
483b7d907d1SIvan Vecera 		return rc;
484b7d907d1SIvan Vecera 
485b7d907d1SIvan Vecera 	/* Read ref_config register */
486b7d907d1SIvan Vecera 	rc = zl3073x_read_u8(zldev, ZL_REG_REF_CONFIG, &ref_config);
487b7d907d1SIvan Vecera 	if (rc)
488b7d907d1SIvan Vecera 		return rc;
489b7d907d1SIvan Vecera 
490b7d907d1SIvan Vecera 	input->enabled = FIELD_GET(ZL_REF_CONFIG_ENABLE, ref_config);
491b7d907d1SIvan Vecera 	input->diff = FIELD_GET(ZL_REF_CONFIG_DIFF_EN, ref_config);
492b7d907d1SIvan Vecera 
493b7d907d1SIvan Vecera 	dev_dbg(zldev->dev, "REF%u is %s and configured as %s\n", index,
494b7d907d1SIvan Vecera 		str_enabled_disabled(input->enabled),
495b7d907d1SIvan Vecera 		input->diff ? "differential" : "single-ended");
496b7d907d1SIvan Vecera 
497b7d907d1SIvan Vecera 	return rc;
498b7d907d1SIvan Vecera }
499b7d907d1SIvan Vecera 
500b7d907d1SIvan Vecera /**
501b7d907d1SIvan Vecera  * zl3073x_out_state_fetch - get output state
502b7d907d1SIvan Vecera  * @zldev: pointer to zl3073x_dev structure
503b7d907d1SIvan Vecera  * @index: output index to fetch state for
504b7d907d1SIvan Vecera  *
505b7d907d1SIvan Vecera  * Function fetches information for the given output (not output pin)
506b7d907d1SIvan Vecera  * that are invariant and stores them for later use.
507b7d907d1SIvan Vecera  *
508b7d907d1SIvan Vecera  * Return: 0 on success, <0 on error
509b7d907d1SIvan Vecera  */
510b7d907d1SIvan Vecera static int
zl3073x_out_state_fetch(struct zl3073x_dev * zldev,u8 index)511b7d907d1SIvan Vecera zl3073x_out_state_fetch(struct zl3073x_dev *zldev, u8 index)
512b7d907d1SIvan Vecera {
513b7d907d1SIvan Vecera 	struct zl3073x_out *out = &zldev->out[index];
514b7d907d1SIvan Vecera 	u8 output_ctrl, output_mode;
515b7d907d1SIvan Vecera 	int rc;
516b7d907d1SIvan Vecera 
517b7d907d1SIvan Vecera 	/* Read output configuration */
518b7d907d1SIvan Vecera 	rc = zl3073x_read_u8(zldev, ZL_REG_OUTPUT_CTRL(index), &output_ctrl);
519b7d907d1SIvan Vecera 	if (rc)
520b7d907d1SIvan Vecera 		return rc;
521b7d907d1SIvan Vecera 
522b7d907d1SIvan Vecera 	/* Store info about output enablement and synthesizer the output
523b7d907d1SIvan Vecera 	 * is connected to.
524b7d907d1SIvan Vecera 	 */
525b7d907d1SIvan Vecera 	out->enabled = FIELD_GET(ZL_OUTPUT_CTRL_EN, output_ctrl);
526b7d907d1SIvan Vecera 	out->synth = FIELD_GET(ZL_OUTPUT_CTRL_SYNTH_SEL, output_ctrl);
527b7d907d1SIvan Vecera 
528b7d907d1SIvan Vecera 	dev_dbg(zldev->dev, "OUT%u is %s and connected to SYNTH%u\n", index,
529b7d907d1SIvan Vecera 		str_enabled_disabled(out->enabled), out->synth);
530b7d907d1SIvan Vecera 
531b7d907d1SIvan Vecera 	guard(mutex)(&zldev->multiop_lock);
532b7d907d1SIvan Vecera 
533b7d907d1SIvan Vecera 	/* Read output configuration */
534b7d907d1SIvan Vecera 	rc = zl3073x_mb_op(zldev, ZL_REG_OUTPUT_MB_SEM, ZL_OUTPUT_MB_SEM_RD,
535b7d907d1SIvan Vecera 			   ZL_REG_OUTPUT_MB_MASK, BIT(index));
536b7d907d1SIvan Vecera 	if (rc)
537b7d907d1SIvan Vecera 		return rc;
538b7d907d1SIvan Vecera 
539b7d907d1SIvan Vecera 	/* Read output_mode */
540b7d907d1SIvan Vecera 	rc = zl3073x_read_u8(zldev, ZL_REG_OUTPUT_MODE, &output_mode);
541b7d907d1SIvan Vecera 	if (rc)
542b7d907d1SIvan Vecera 		return rc;
543b7d907d1SIvan Vecera 
544b7d907d1SIvan Vecera 	/* Extract and store output signal format */
545b7d907d1SIvan Vecera 	out->signal_format = FIELD_GET(ZL_OUTPUT_MODE_SIGNAL_FORMAT,
546b7d907d1SIvan Vecera 				       output_mode);
547b7d907d1SIvan Vecera 
548b7d907d1SIvan Vecera 	dev_dbg(zldev->dev, "OUT%u has signal format 0x%02x\n", index,
549b7d907d1SIvan Vecera 		out->signal_format);
550b7d907d1SIvan Vecera 
551b7d907d1SIvan Vecera 	return rc;
552b7d907d1SIvan Vecera }
553b7d907d1SIvan Vecera 
554b7d907d1SIvan Vecera /**
555b7d907d1SIvan Vecera  * zl3073x_synth_state_fetch - get synth state
556b7d907d1SIvan Vecera  * @zldev: pointer to zl3073x_dev structure
557b7d907d1SIvan Vecera  * @index: synth index to fetch state for
558b7d907d1SIvan Vecera  *
559b7d907d1SIvan Vecera  * Function fetches information for the given synthesizer that are
560b7d907d1SIvan Vecera  * invariant and stores them for later use.
561b7d907d1SIvan Vecera  *
562b7d907d1SIvan Vecera  * Return: 0 on success, <0 on error
563b7d907d1SIvan Vecera  */
564b7d907d1SIvan Vecera static int
zl3073x_synth_state_fetch(struct zl3073x_dev * zldev,u8 index)565b7d907d1SIvan Vecera zl3073x_synth_state_fetch(struct zl3073x_dev *zldev, u8 index)
566b7d907d1SIvan Vecera {
567b7d907d1SIvan Vecera 	struct zl3073x_synth *synth = &zldev->synth[index];
568b7d907d1SIvan Vecera 	u16 base, m, n;
569b7d907d1SIvan Vecera 	u8 synth_ctrl;
570b7d907d1SIvan Vecera 	u32 mult;
571b7d907d1SIvan Vecera 	int rc;
572b7d907d1SIvan Vecera 
573b7d907d1SIvan Vecera 	/* Read synth control register */
574b7d907d1SIvan Vecera 	rc = zl3073x_read_u8(zldev, ZL_REG_SYNTH_CTRL(index), &synth_ctrl);
575b7d907d1SIvan Vecera 	if (rc)
576b7d907d1SIvan Vecera 		return rc;
577b7d907d1SIvan Vecera 
578b7d907d1SIvan Vecera 	/* Store info about synth enablement and DPLL channel the synth is
579b7d907d1SIvan Vecera 	 * driven by.
580b7d907d1SIvan Vecera 	 */
581b7d907d1SIvan Vecera 	synth->enabled = FIELD_GET(ZL_SYNTH_CTRL_EN, synth_ctrl);
582b7d907d1SIvan Vecera 	synth->dpll = FIELD_GET(ZL_SYNTH_CTRL_DPLL_SEL, synth_ctrl);
583b7d907d1SIvan Vecera 
584b7d907d1SIvan Vecera 	dev_dbg(zldev->dev, "SYNTH%u is %s and driven by DPLL%u\n", index,
585b7d907d1SIvan Vecera 		str_enabled_disabled(synth->enabled), synth->dpll);
586b7d907d1SIvan Vecera 
587b7d907d1SIvan Vecera 	guard(mutex)(&zldev->multiop_lock);
588b7d907d1SIvan Vecera 
589b7d907d1SIvan Vecera 	/* Read synth configuration */
590b7d907d1SIvan Vecera 	rc = zl3073x_mb_op(zldev, ZL_REG_SYNTH_MB_SEM, ZL_SYNTH_MB_SEM_RD,
591b7d907d1SIvan Vecera 			   ZL_REG_SYNTH_MB_MASK, BIT(index));
592b7d907d1SIvan Vecera 	if (rc)
593b7d907d1SIvan Vecera 		return rc;
594b7d907d1SIvan Vecera 
595b7d907d1SIvan Vecera 	/* The output frequency is determined by the following formula:
596b7d907d1SIvan Vecera 	 * base * multiplier * numerator / denominator
597b7d907d1SIvan Vecera 	 *
598b7d907d1SIvan Vecera 	 * Read registers with these values
599b7d907d1SIvan Vecera 	 */
600b7d907d1SIvan Vecera 	rc = zl3073x_read_u16(zldev, ZL_REG_SYNTH_FREQ_BASE, &base);
601b7d907d1SIvan Vecera 	if (rc)
602b7d907d1SIvan Vecera 		return rc;
603b7d907d1SIvan Vecera 
604b7d907d1SIvan Vecera 	rc = zl3073x_read_u32(zldev, ZL_REG_SYNTH_FREQ_MULT, &mult);
605b7d907d1SIvan Vecera 	if (rc)
606b7d907d1SIvan Vecera 		return rc;
607b7d907d1SIvan Vecera 
608b7d907d1SIvan Vecera 	rc = zl3073x_read_u16(zldev, ZL_REG_SYNTH_FREQ_M, &m);
609b7d907d1SIvan Vecera 	if (rc)
610b7d907d1SIvan Vecera 		return rc;
611b7d907d1SIvan Vecera 
612b7d907d1SIvan Vecera 	rc = zl3073x_read_u16(zldev, ZL_REG_SYNTH_FREQ_N, &n);
613b7d907d1SIvan Vecera 	if (rc)
614b7d907d1SIvan Vecera 		return rc;
615b7d907d1SIvan Vecera 
616b7d907d1SIvan Vecera 	/* Check denominator for zero to avoid div by 0 */
617b7d907d1SIvan Vecera 	if (!n) {
618b7d907d1SIvan Vecera 		dev_err(zldev->dev,
619b7d907d1SIvan Vecera 			"Zero divisor for SYNTH%u retrieved from device\n",
620b7d907d1SIvan Vecera 			index);
621b7d907d1SIvan Vecera 		return -EINVAL;
622b7d907d1SIvan Vecera 	}
623b7d907d1SIvan Vecera 
624b7d907d1SIvan Vecera 	/* Compute and store synth frequency */
625b7d907d1SIvan Vecera 	zldev->synth[index].freq = div_u64(mul_u32_u32(base * m, mult), n);
626b7d907d1SIvan Vecera 
627b7d907d1SIvan Vecera 	dev_dbg(zldev->dev, "SYNTH%u frequency: %u Hz\n", index,
628b7d907d1SIvan Vecera 		zldev->synth[index].freq);
629b7d907d1SIvan Vecera 
630b7d907d1SIvan Vecera 	return rc;
631b7d907d1SIvan Vecera }
632b7d907d1SIvan Vecera 
633b7d907d1SIvan Vecera static int
zl3073x_dev_state_fetch(struct zl3073x_dev * zldev)634b7d907d1SIvan Vecera zl3073x_dev_state_fetch(struct zl3073x_dev *zldev)
635b7d907d1SIvan Vecera {
636b7d907d1SIvan Vecera 	int rc;
637b7d907d1SIvan Vecera 	u8 i;
638b7d907d1SIvan Vecera 
639b7d907d1SIvan Vecera 	for (i = 0; i < ZL3073X_NUM_REFS; i++) {
640b7d907d1SIvan Vecera 		rc = zl3073x_ref_state_fetch(zldev, i);
641b7d907d1SIvan Vecera 		if (rc) {
642b7d907d1SIvan Vecera 			dev_err(zldev->dev,
643b7d907d1SIvan Vecera 				"Failed to fetch input state: %pe\n",
644b7d907d1SIvan Vecera 				ERR_PTR(rc));
645b7d907d1SIvan Vecera 			return rc;
646b7d907d1SIvan Vecera 		}
647b7d907d1SIvan Vecera 	}
648b7d907d1SIvan Vecera 
649b7d907d1SIvan Vecera 	for (i = 0; i < ZL3073X_NUM_SYNTHS; i++) {
650b7d907d1SIvan Vecera 		rc = zl3073x_synth_state_fetch(zldev, i);
651b7d907d1SIvan Vecera 		if (rc) {
652b7d907d1SIvan Vecera 			dev_err(zldev->dev,
653b7d907d1SIvan Vecera 				"Failed to fetch synth state: %pe\n",
654b7d907d1SIvan Vecera 				ERR_PTR(rc));
655b7d907d1SIvan Vecera 			return rc;
656b7d907d1SIvan Vecera 		}
657b7d907d1SIvan Vecera 	}
658b7d907d1SIvan Vecera 
659b7d907d1SIvan Vecera 	for (i = 0; i < ZL3073X_NUM_OUTS; i++) {
660b7d907d1SIvan Vecera 		rc = zl3073x_out_state_fetch(zldev, i);
661b7d907d1SIvan Vecera 		if (rc) {
662b7d907d1SIvan Vecera 			dev_err(zldev->dev,
663b7d907d1SIvan Vecera 				"Failed to fetch output state: %pe\n",
664b7d907d1SIvan Vecera 				ERR_PTR(rc));
665b7d907d1SIvan Vecera 			return rc;
666b7d907d1SIvan Vecera 		}
667b7d907d1SIvan Vecera 	}
668b7d907d1SIvan Vecera 
669b7d907d1SIvan Vecera 	return rc;
670b7d907d1SIvan Vecera }
671b7d907d1SIvan Vecera 
67286ed4cd5SIvan Vecera /**
67386ed4cd5SIvan Vecera  * zl3073x_ref_phase_offsets_update - update reference phase offsets
67486ed4cd5SIvan Vecera  * @zldev: pointer to zl3073x_dev structure
675b7dbde2bSIvan Vecera  * @channel: DPLL channel number or -1
67686ed4cd5SIvan Vecera  *
677b7dbde2bSIvan Vecera  * The function asks device to update phase offsets latch registers with
678b7dbde2bSIvan Vecera  * the latest measured values. There are 2 sets of latch registers:
679b7dbde2bSIvan Vecera  *
680b7dbde2bSIvan Vecera  * 1) Up to 5 DPLL-to-connected-ref registers that contain phase offset
681b7dbde2bSIvan Vecera  *    values between particular DPLL channel and its *connected* input
682b7dbde2bSIvan Vecera  *    reference.
683b7dbde2bSIvan Vecera  *
684b7dbde2bSIvan Vecera  * 2) 10 selected-DPLL-to-all-ref registers that contain phase offset values
685b7dbde2bSIvan Vecera  *    between selected DPLL channel and all input references.
686b7dbde2bSIvan Vecera  *
687b7dbde2bSIvan Vecera  * If the caller is interested in 2) then it has to pass DPLL channel number
688b7dbde2bSIvan Vecera  * in @channel parameter. If it is interested only in 1) then it should pass
689b7dbde2bSIvan Vecera  * @channel parameter with value of -1.
69086ed4cd5SIvan Vecera  *
69186ed4cd5SIvan Vecera  * Return: 0 on success, <0 on error
69286ed4cd5SIvan Vecera  */
zl3073x_ref_phase_offsets_update(struct zl3073x_dev * zldev,int channel)693b7dbde2bSIvan Vecera int zl3073x_ref_phase_offsets_update(struct zl3073x_dev *zldev, int channel)
69486ed4cd5SIvan Vecera {
69586ed4cd5SIvan Vecera 	int rc;
69686ed4cd5SIvan Vecera 
69786ed4cd5SIvan Vecera 	/* Per datasheet we have to wait for 'dpll_ref_phase_err_rqst_rd'
69886ed4cd5SIvan Vecera 	 * to be zero to ensure that the measured data are coherent.
69986ed4cd5SIvan Vecera 	 */
70086ed4cd5SIvan Vecera 	rc = zl3073x_poll_zero_u8(zldev, ZL_REG_REF_PHASE_ERR_READ_RQST,
70186ed4cd5SIvan Vecera 				  ZL_REF_PHASE_ERR_READ_RQST_RD);
70286ed4cd5SIvan Vecera 	if (rc)
70386ed4cd5SIvan Vecera 		return rc;
70486ed4cd5SIvan Vecera 
705b7dbde2bSIvan Vecera 	/* Select DPLL channel if it is specified */
706b7dbde2bSIvan Vecera 	if (channel != -1) {
707b7dbde2bSIvan Vecera 		rc = zl3073x_write_u8(zldev, ZL_REG_DPLL_MEAS_IDX, channel);
708b7dbde2bSIvan Vecera 		if (rc)
709b7dbde2bSIvan Vecera 			return rc;
710b7dbde2bSIvan Vecera 	}
711b7dbde2bSIvan Vecera 
71286ed4cd5SIvan Vecera 	/* Request to update phase offsets measurement values */
71386ed4cd5SIvan Vecera 	rc = zl3073x_write_u8(zldev, ZL_REG_REF_PHASE_ERR_READ_RQST,
71486ed4cd5SIvan Vecera 			      ZL_REF_PHASE_ERR_READ_RQST_RD);
71586ed4cd5SIvan Vecera 	if (rc)
71686ed4cd5SIvan Vecera 		return rc;
71786ed4cd5SIvan Vecera 
71886ed4cd5SIvan Vecera 	/* Wait for finish */
71986ed4cd5SIvan Vecera 	return zl3073x_poll_zero_u8(zldev, ZL_REG_REF_PHASE_ERR_READ_RQST,
72086ed4cd5SIvan Vecera 				    ZL_REF_PHASE_ERR_READ_RQST_RD);
72186ed4cd5SIvan Vecera }
72286ed4cd5SIvan Vecera 
723*904c99eaSIvan Vecera /**
724*904c99eaSIvan Vecera  * zl3073x_ref_ffo_update - update reference fractional frequency offsets
725*904c99eaSIvan Vecera  * @zldev: pointer to zl3073x_dev structure
726*904c99eaSIvan Vecera  *
727*904c99eaSIvan Vecera  * The function asks device to update fractional frequency offsets latch
728*904c99eaSIvan Vecera  * registers the latest measured values, reads and stores them into
729*904c99eaSIvan Vecera  *
730*904c99eaSIvan Vecera  * Return: 0 on success, <0 on error
731*904c99eaSIvan Vecera  */
732*904c99eaSIvan Vecera static int
zl3073x_ref_ffo_update(struct zl3073x_dev * zldev)733*904c99eaSIvan Vecera zl3073x_ref_ffo_update(struct zl3073x_dev *zldev)
734*904c99eaSIvan Vecera {
735*904c99eaSIvan Vecera 	int i, rc;
736*904c99eaSIvan Vecera 
737*904c99eaSIvan Vecera 	/* Per datasheet we have to wait for 'ref_freq_meas_ctrl' to be zero
738*904c99eaSIvan Vecera 	 * to ensure that the measured data are coherent.
739*904c99eaSIvan Vecera 	 */
740*904c99eaSIvan Vecera 	rc = zl3073x_poll_zero_u8(zldev, ZL_REG_REF_FREQ_MEAS_CTRL,
741*904c99eaSIvan Vecera 				  ZL_REF_FREQ_MEAS_CTRL);
742*904c99eaSIvan Vecera 	if (rc)
743*904c99eaSIvan Vecera 		return rc;
744*904c99eaSIvan Vecera 
745*904c99eaSIvan Vecera 	/* Select all references for measurement */
746*904c99eaSIvan Vecera 	rc = zl3073x_write_u8(zldev, ZL_REG_REF_FREQ_MEAS_MASK_3_0,
747*904c99eaSIvan Vecera 			      GENMASK(7, 0)); /* REF0P..REF3N */
748*904c99eaSIvan Vecera 	if (rc)
749*904c99eaSIvan Vecera 		return rc;
750*904c99eaSIvan Vecera 	rc = zl3073x_write_u8(zldev, ZL_REG_REF_FREQ_MEAS_MASK_4,
751*904c99eaSIvan Vecera 			      GENMASK(1, 0)); /* REF4P..REF4N */
752*904c99eaSIvan Vecera 	if (rc)
753*904c99eaSIvan Vecera 		return rc;
754*904c99eaSIvan Vecera 
755*904c99eaSIvan Vecera 	/* Request frequency offset measurement */
756*904c99eaSIvan Vecera 	rc = zl3073x_write_u8(zldev, ZL_REG_REF_FREQ_MEAS_CTRL,
757*904c99eaSIvan Vecera 			      ZL_REF_FREQ_MEAS_CTRL_REF_FREQ_OFF);
758*904c99eaSIvan Vecera 	if (rc)
759*904c99eaSIvan Vecera 		return rc;
760*904c99eaSIvan Vecera 
761*904c99eaSIvan Vecera 	/* Wait for finish */
762*904c99eaSIvan Vecera 	rc = zl3073x_poll_zero_u8(zldev, ZL_REG_REF_FREQ_MEAS_CTRL,
763*904c99eaSIvan Vecera 				  ZL_REF_FREQ_MEAS_CTRL);
764*904c99eaSIvan Vecera 	if (rc)
765*904c99eaSIvan Vecera 		return rc;
766*904c99eaSIvan Vecera 
767*904c99eaSIvan Vecera 	/* Read DPLL-to-REFx frequency offset measurements */
768*904c99eaSIvan Vecera 	for (i = 0; i < ZL3073X_NUM_REFS; i++) {
769*904c99eaSIvan Vecera 		s32 value;
770*904c99eaSIvan Vecera 
771*904c99eaSIvan Vecera 		/* Read value stored in units of 2^-32 signed */
772*904c99eaSIvan Vecera 		rc = zl3073x_read_u32(zldev, ZL_REG_REF_FREQ(i), &value);
773*904c99eaSIvan Vecera 		if (rc)
774*904c99eaSIvan Vecera 			return rc;
775*904c99eaSIvan Vecera 
776*904c99eaSIvan Vecera 		/* Convert to ppm -> ffo = (10^6 * value) / 2^32 */
777*904c99eaSIvan Vecera 		zldev->ref[i].ffo = mul_s64_u64_shr(value, 1000000, 32);
778*904c99eaSIvan Vecera 	}
779*904c99eaSIvan Vecera 
780*904c99eaSIvan Vecera 	return 0;
781*904c99eaSIvan Vecera }
782*904c99eaSIvan Vecera 
78375a71eccSIvan Vecera static void
zl3073x_dev_periodic_work(struct kthread_work * work)78475a71eccSIvan Vecera zl3073x_dev_periodic_work(struct kthread_work *work)
78575a71eccSIvan Vecera {
78675a71eccSIvan Vecera 	struct zl3073x_dev *zldev = container_of(work, struct zl3073x_dev,
78775a71eccSIvan Vecera 						 work.work);
78875a71eccSIvan Vecera 	struct zl3073x_dpll *zldpll;
78986ed4cd5SIvan Vecera 	int rc;
79086ed4cd5SIvan Vecera 
79186ed4cd5SIvan Vecera 	/* Update DPLL-to-connected-ref phase offsets registers */
792b7dbde2bSIvan Vecera 	rc = zl3073x_ref_phase_offsets_update(zldev, -1);
79386ed4cd5SIvan Vecera 	if (rc)
79486ed4cd5SIvan Vecera 		dev_warn(zldev->dev, "Failed to update phase offsets: %pe\n",
79586ed4cd5SIvan Vecera 			 ERR_PTR(rc));
79675a71eccSIvan Vecera 
797*904c99eaSIvan Vecera 	/* Update references' fractional frequency offsets */
798*904c99eaSIvan Vecera 	rc = zl3073x_ref_ffo_update(zldev);
799*904c99eaSIvan Vecera 	if (rc)
800*904c99eaSIvan Vecera 		dev_warn(zldev->dev,
801*904c99eaSIvan Vecera 			 "Failed to update fractional frequency offsets: %pe\n",
802*904c99eaSIvan Vecera 			 ERR_PTR(rc));
803*904c99eaSIvan Vecera 
80475a71eccSIvan Vecera 	list_for_each_entry(zldpll, &zldev->dplls, list)
80575a71eccSIvan Vecera 		zl3073x_dpll_changes_check(zldpll);
80675a71eccSIvan Vecera 
80775a71eccSIvan Vecera 	/* Run twice a second */
80875a71eccSIvan Vecera 	kthread_queue_delayed_work(zldev->kworker, &zldev->work,
80975a71eccSIvan Vecera 				   msecs_to_jiffies(500));
81075a71eccSIvan Vecera }
81175a71eccSIvan Vecera 
zl3073x_dev_dpll_fini(void * ptr)81275a71eccSIvan Vecera static void zl3073x_dev_dpll_fini(void *ptr)
81375a71eccSIvan Vecera {
81475a71eccSIvan Vecera 	struct zl3073x_dpll *zldpll, *next;
81575a71eccSIvan Vecera 	struct zl3073x_dev *zldev = ptr;
81675a71eccSIvan Vecera 
81775a71eccSIvan Vecera 	/* Stop monitoring thread */
81875a71eccSIvan Vecera 	if (zldev->kworker) {
81975a71eccSIvan Vecera 		kthread_cancel_delayed_work_sync(&zldev->work);
82075a71eccSIvan Vecera 		kthread_destroy_worker(zldev->kworker);
82175a71eccSIvan Vecera 		zldev->kworker = NULL;
82275a71eccSIvan Vecera 	}
82375a71eccSIvan Vecera 
82475a71eccSIvan Vecera 	/* Release DPLLs */
82575a71eccSIvan Vecera 	list_for_each_entry_safe(zldpll, next, &zldev->dplls, list) {
82675a71eccSIvan Vecera 		zl3073x_dpll_unregister(zldpll);
82775a71eccSIvan Vecera 		list_del(&zldpll->list);
82875a71eccSIvan Vecera 		zl3073x_dpll_free(zldpll);
82975a71eccSIvan Vecera 	}
83075a71eccSIvan Vecera }
83175a71eccSIvan Vecera 
83275a71eccSIvan Vecera static int
zl3073x_devm_dpll_init(struct zl3073x_dev * zldev,u8 num_dplls)83375a71eccSIvan Vecera zl3073x_devm_dpll_init(struct zl3073x_dev *zldev, u8 num_dplls)
83475a71eccSIvan Vecera {
83575a71eccSIvan Vecera 	struct kthread_worker *kworker;
83675a71eccSIvan Vecera 	struct zl3073x_dpll *zldpll;
83775a71eccSIvan Vecera 	unsigned int i;
83875a71eccSIvan Vecera 	int rc;
83975a71eccSIvan Vecera 
84075a71eccSIvan Vecera 	INIT_LIST_HEAD(&zldev->dplls);
84175a71eccSIvan Vecera 
84275a71eccSIvan Vecera 	/* Initialize all DPLLs */
84375a71eccSIvan Vecera 	for (i = 0; i < num_dplls; i++) {
84475a71eccSIvan Vecera 		zldpll = zl3073x_dpll_alloc(zldev, i);
84575a71eccSIvan Vecera 		if (IS_ERR(zldpll)) {
84675a71eccSIvan Vecera 			dev_err_probe(zldev->dev, PTR_ERR(zldpll),
84775a71eccSIvan Vecera 				      "Failed to alloc DPLL%u\n", i);
84875a71eccSIvan Vecera 			rc = PTR_ERR(zldpll);
84975a71eccSIvan Vecera 			goto error;
85075a71eccSIvan Vecera 		}
85175a71eccSIvan Vecera 
85275a71eccSIvan Vecera 		rc = zl3073x_dpll_register(zldpll);
85375a71eccSIvan Vecera 		if (rc) {
85475a71eccSIvan Vecera 			dev_err_probe(zldev->dev, rc,
85575a71eccSIvan Vecera 				      "Failed to register DPLL%u\n", i);
85675a71eccSIvan Vecera 			zl3073x_dpll_free(zldpll);
85775a71eccSIvan Vecera 			goto error;
85875a71eccSIvan Vecera 		}
85975a71eccSIvan Vecera 
86075a71eccSIvan Vecera 		list_add_tail(&zldpll->list, &zldev->dplls);
86175a71eccSIvan Vecera 	}
86275a71eccSIvan Vecera 
86375a71eccSIvan Vecera 	/* Perform initial firmware fine phase correction */
86475a71eccSIvan Vecera 	rc = zl3073x_dpll_init_fine_phase_adjust(zldev);
86575a71eccSIvan Vecera 	if (rc) {
86675a71eccSIvan Vecera 		dev_err_probe(zldev->dev, rc,
86775a71eccSIvan Vecera 			      "Failed to init fine phase correction\n");
86875a71eccSIvan Vecera 		goto error;
86975a71eccSIvan Vecera 	}
87075a71eccSIvan Vecera 
87175a71eccSIvan Vecera 	/* Initialize monitoring thread */
87275a71eccSIvan Vecera 	kthread_init_delayed_work(&zldev->work, zl3073x_dev_periodic_work);
87375a71eccSIvan Vecera 	kworker = kthread_run_worker(0, "zl3073x-%s", dev_name(zldev->dev));
87475a71eccSIvan Vecera 	if (IS_ERR(kworker)) {
87575a71eccSIvan Vecera 		rc = PTR_ERR(kworker);
87675a71eccSIvan Vecera 		goto error;
87775a71eccSIvan Vecera 	}
87875a71eccSIvan Vecera 
87975a71eccSIvan Vecera 	zldev->kworker = kworker;
88075a71eccSIvan Vecera 	kthread_queue_delayed_work(zldev->kworker, &zldev->work, 0);
88175a71eccSIvan Vecera 
88275a71eccSIvan Vecera 	/* Add devres action to release DPLL related resources */
88375a71eccSIvan Vecera 	rc = devm_add_action_or_reset(zldev->dev, zl3073x_dev_dpll_fini, zldev);
88475a71eccSIvan Vecera 	if (rc)
88575a71eccSIvan Vecera 		goto error;
88675a71eccSIvan Vecera 
88775a71eccSIvan Vecera 	return 0;
88875a71eccSIvan Vecera 
88975a71eccSIvan Vecera error:
89075a71eccSIvan Vecera 	zl3073x_dev_dpll_fini(zldev);
89175a71eccSIvan Vecera 
89275a71eccSIvan Vecera 	return rc;
89375a71eccSIvan Vecera }
89475a71eccSIvan Vecera 
8952df8e64eSIvan Vecera /**
89686ed4cd5SIvan Vecera  * zl3073x_dev_phase_meas_setup - setup phase offset measurement
89786ed4cd5SIvan Vecera  * @zldev: pointer to zl3073x_dev structure
89886ed4cd5SIvan Vecera  * @num_channels: number of DPLL channels
89986ed4cd5SIvan Vecera  *
90086ed4cd5SIvan Vecera  * Enable phase offset measurement block, set measurement averaging factor
90186ed4cd5SIvan Vecera  * and enable DPLL-to-its-ref phase measurement for all DPLLs.
90286ed4cd5SIvan Vecera  *
90386ed4cd5SIvan Vecera  * Returns: 0 on success, <0 on error
90486ed4cd5SIvan Vecera  */
90586ed4cd5SIvan Vecera static int
zl3073x_dev_phase_meas_setup(struct zl3073x_dev * zldev,int num_channels)90686ed4cd5SIvan Vecera zl3073x_dev_phase_meas_setup(struct zl3073x_dev *zldev, int num_channels)
90786ed4cd5SIvan Vecera {
90886ed4cd5SIvan Vecera 	u8 dpll_meas_ctrl, mask;
90986ed4cd5SIvan Vecera 	int i, rc;
91086ed4cd5SIvan Vecera 
91186ed4cd5SIvan Vecera 	/* Read DPLL phase measurement control register */
91286ed4cd5SIvan Vecera 	rc = zl3073x_read_u8(zldev, ZL_REG_DPLL_MEAS_CTRL, &dpll_meas_ctrl);
91386ed4cd5SIvan Vecera 	if (rc)
91486ed4cd5SIvan Vecera 		return rc;
91586ed4cd5SIvan Vecera 
91686ed4cd5SIvan Vecera 	/* Setup phase measurement averaging factor */
91786ed4cd5SIvan Vecera 	dpll_meas_ctrl &= ~ZL_DPLL_MEAS_CTRL_AVG_FACTOR;
91886ed4cd5SIvan Vecera 	dpll_meas_ctrl |= FIELD_PREP(ZL_DPLL_MEAS_CTRL_AVG_FACTOR, 3);
91986ed4cd5SIvan Vecera 
92086ed4cd5SIvan Vecera 	/* Enable DPLL measurement block */
92186ed4cd5SIvan Vecera 	dpll_meas_ctrl |= ZL_DPLL_MEAS_CTRL_EN;
92286ed4cd5SIvan Vecera 
92386ed4cd5SIvan Vecera 	/* Update phase measurement control register */
92486ed4cd5SIvan Vecera 	rc = zl3073x_write_u8(zldev, ZL_REG_DPLL_MEAS_CTRL, dpll_meas_ctrl);
92586ed4cd5SIvan Vecera 	if (rc)
92686ed4cd5SIvan Vecera 		return rc;
92786ed4cd5SIvan Vecera 
92886ed4cd5SIvan Vecera 	/* Enable DPLL-to-connected-ref measurement for each channel */
92986ed4cd5SIvan Vecera 	for (i = 0, mask = 0; i < num_channels; i++)
93086ed4cd5SIvan Vecera 		mask |= BIT(i);
93186ed4cd5SIvan Vecera 
93286ed4cd5SIvan Vecera 	return zl3073x_write_u8(zldev, ZL_REG_DPLL_PHASE_ERR_READ_MASK, mask);
93386ed4cd5SIvan Vecera }
93486ed4cd5SIvan Vecera 
93586ed4cd5SIvan Vecera /**
9362df8e64eSIvan Vecera  * zl3073x_dev_probe - initialize zl3073x device
9372df8e64eSIvan Vecera  * @zldev: pointer to zl3073x device
9382df8e64eSIvan Vecera  * @chip_info: chip info based on compatible
9392df8e64eSIvan Vecera  *
9402df8e64eSIvan Vecera  * Common initialization of zl3073x device structure.
9412df8e64eSIvan Vecera  *
9422df8e64eSIvan Vecera  * Returns: 0 on success, <0 on error
9432df8e64eSIvan Vecera  */
zl3073x_dev_probe(struct zl3073x_dev * zldev,const struct zl3073x_chip_info * chip_info)9442df8e64eSIvan Vecera int zl3073x_dev_probe(struct zl3073x_dev *zldev,
9452df8e64eSIvan Vecera 		      const struct zl3073x_chip_info *chip_info)
9462df8e64eSIvan Vecera {
9472df8e64eSIvan Vecera 	u16 id, revision, fw_ver;
9482df8e64eSIvan Vecera 	unsigned int i;
9492df8e64eSIvan Vecera 	u32 cfg_ver;
9502df8e64eSIvan Vecera 	int rc;
9512df8e64eSIvan Vecera 
9522df8e64eSIvan Vecera 	/* Read chip ID */
9532df8e64eSIvan Vecera 	rc = zl3073x_read_u16(zldev, ZL_REG_ID, &id);
9542df8e64eSIvan Vecera 	if (rc)
9552df8e64eSIvan Vecera 		return rc;
9562df8e64eSIvan Vecera 
9572df8e64eSIvan Vecera 	/* Check it matches */
9582df8e64eSIvan Vecera 	for (i = 0; i < chip_info->num_ids; i++) {
9592df8e64eSIvan Vecera 		if (id == chip_info->ids[i])
9602df8e64eSIvan Vecera 			break;
9612df8e64eSIvan Vecera 	}
9622df8e64eSIvan Vecera 
9632df8e64eSIvan Vecera 	if (i == chip_info->num_ids) {
9642df8e64eSIvan Vecera 		return dev_err_probe(zldev->dev, -ENODEV,
9652df8e64eSIvan Vecera 				     "Unknown or non-match chip ID: 0x%0x\n",
9662df8e64eSIvan Vecera 				     id);
9672df8e64eSIvan Vecera 	}
9682df8e64eSIvan Vecera 
9692df8e64eSIvan Vecera 	/* Read revision, firmware version and custom config version */
9702df8e64eSIvan Vecera 	rc = zl3073x_read_u16(zldev, ZL_REG_REVISION, &revision);
9712df8e64eSIvan Vecera 	if (rc)
9722df8e64eSIvan Vecera 		return rc;
9732df8e64eSIvan Vecera 	rc = zl3073x_read_u16(zldev, ZL_REG_FW_VER, &fw_ver);
9742df8e64eSIvan Vecera 	if (rc)
9752df8e64eSIvan Vecera 		return rc;
9762df8e64eSIvan Vecera 	rc = zl3073x_read_u32(zldev, ZL_REG_CUSTOM_CONFIG_VER, &cfg_ver);
9772df8e64eSIvan Vecera 	if (rc)
9782df8e64eSIvan Vecera 		return rc;
9792df8e64eSIvan Vecera 
9802df8e64eSIvan Vecera 	dev_dbg(zldev->dev, "ChipID(%X), ChipRev(%X), FwVer(%u)\n", id,
9812df8e64eSIvan Vecera 		revision, fw_ver);
9822df8e64eSIvan Vecera 	dev_dbg(zldev->dev, "Custom config version: %lu.%lu.%lu.%lu\n",
9832df8e64eSIvan Vecera 		FIELD_GET(GENMASK(31, 24), cfg_ver),
9842df8e64eSIvan Vecera 		FIELD_GET(GENMASK(23, 16), cfg_ver),
9852df8e64eSIvan Vecera 		FIELD_GET(GENMASK(15, 8), cfg_ver),
9862df8e64eSIvan Vecera 		FIELD_GET(GENMASK(7, 0), cfg_ver));
9872df8e64eSIvan Vecera 
9882df8e64eSIvan Vecera 	/* Generate random clock ID as the device has not such property that
9892df8e64eSIvan Vecera 	 * could be used for this purpose. A user can later change this value
9902df8e64eSIvan Vecera 	 * using devlink.
9912df8e64eSIvan Vecera 	 */
9922df8e64eSIvan Vecera 	zldev->clock_id = get_random_u64();
9932df8e64eSIvan Vecera 
9942df8e64eSIvan Vecera 	/* Initialize mutex for operations where multiple reads, writes
9952df8e64eSIvan Vecera 	 * and/or polls are required to be done atomically.
9962df8e64eSIvan Vecera 	 */
9972df8e64eSIvan Vecera 	rc = devm_mutex_init(zldev->dev, &zldev->multiop_lock);
9982df8e64eSIvan Vecera 	if (rc)
9992df8e64eSIvan Vecera 		return dev_err_probe(zldev->dev, rc,
10002df8e64eSIvan Vecera 				     "Failed to initialize mutex\n");
10012df8e64eSIvan Vecera 
1002b7d907d1SIvan Vecera 	/* Fetch device state */
1003b7d907d1SIvan Vecera 	rc = zl3073x_dev_state_fetch(zldev);
1004b7d907d1SIvan Vecera 	if (rc)
1005b7d907d1SIvan Vecera 		return rc;
1006b7d907d1SIvan Vecera 
100786ed4cd5SIvan Vecera 	/* Setup phase offset measurement block */
100886ed4cd5SIvan Vecera 	rc = zl3073x_dev_phase_meas_setup(zldev, chip_info->num_channels);
100986ed4cd5SIvan Vecera 	if (rc)
101086ed4cd5SIvan Vecera 		return dev_err_probe(zldev->dev, rc,
101186ed4cd5SIvan Vecera 				     "Failed to setup phase measurement\n");
101286ed4cd5SIvan Vecera 
101375a71eccSIvan Vecera 	/* Register DPLL channels */
101475a71eccSIvan Vecera 	rc = zl3073x_devm_dpll_init(zldev, chip_info->num_channels);
101575a71eccSIvan Vecera 	if (rc)
101675a71eccSIvan Vecera 		return rc;
101775a71eccSIvan Vecera 
10182df8e64eSIvan Vecera 	/* Register the devlink instance and parameters */
10192df8e64eSIvan Vecera 	rc = zl3073x_devlink_register(zldev);
10202df8e64eSIvan Vecera 	if (rc)
10212df8e64eSIvan Vecera 		return dev_err_probe(zldev->dev, rc,
10222df8e64eSIvan Vecera 				     "Failed to register devlink instance\n");
10232df8e64eSIvan Vecera 
10242df8e64eSIvan Vecera 	return 0;
10252df8e64eSIvan Vecera }
10262df8e64eSIvan Vecera EXPORT_SYMBOL_NS_GPL(zl3073x_dev_probe, "ZL3073X");
10272df8e64eSIvan Vecera 
10282df8e64eSIvan Vecera MODULE_AUTHOR("Ivan Vecera <ivecera@redhat.com>");
10292df8e64eSIvan Vecera MODULE_DESCRIPTION("Microchip ZL3073x core driver");
10302df8e64eSIvan Vecera MODULE_LICENSE("GPL");
1031