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