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 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 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 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 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 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 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 675*b7dbde2bSIvan Vecera * @channel: DPLL channel number or -1 67686ed4cd5SIvan Vecera * 677*b7dbde2bSIvan Vecera * The function asks device to update phase offsets latch registers with 678*b7dbde2bSIvan Vecera * the latest measured values. There are 2 sets of latch registers: 679*b7dbde2bSIvan Vecera * 680*b7dbde2bSIvan Vecera * 1) Up to 5 DPLL-to-connected-ref registers that contain phase offset 681*b7dbde2bSIvan Vecera * values between particular DPLL channel and its *connected* input 682*b7dbde2bSIvan Vecera * reference. 683*b7dbde2bSIvan Vecera * 684*b7dbde2bSIvan Vecera * 2) 10 selected-DPLL-to-all-ref registers that contain phase offset values 685*b7dbde2bSIvan Vecera * between selected DPLL channel and all input references. 686*b7dbde2bSIvan Vecera * 687*b7dbde2bSIvan Vecera * If the caller is interested in 2) then it has to pass DPLL channel number 688*b7dbde2bSIvan Vecera * in @channel parameter. If it is interested only in 1) then it should pass 689*b7dbde2bSIvan Vecera * @channel parameter with value of -1. 69086ed4cd5SIvan Vecera * 69186ed4cd5SIvan Vecera * Return: 0 on success, <0 on error 69286ed4cd5SIvan Vecera */ 693*b7dbde2bSIvan 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 705*b7dbde2bSIvan Vecera /* Select DPLL channel if it is specified */ 706*b7dbde2bSIvan Vecera if (channel != -1) { 707*b7dbde2bSIvan Vecera rc = zl3073x_write_u8(zldev, ZL_REG_DPLL_MEAS_IDX, channel); 708*b7dbde2bSIvan Vecera if (rc) 709*b7dbde2bSIvan Vecera return rc; 710*b7dbde2bSIvan Vecera } 711*b7dbde2bSIvan 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 72375a71eccSIvan Vecera static void 72475a71eccSIvan Vecera zl3073x_dev_periodic_work(struct kthread_work *work) 72575a71eccSIvan Vecera { 72675a71eccSIvan Vecera struct zl3073x_dev *zldev = container_of(work, struct zl3073x_dev, 72775a71eccSIvan Vecera work.work); 72875a71eccSIvan Vecera struct zl3073x_dpll *zldpll; 72986ed4cd5SIvan Vecera int rc; 73086ed4cd5SIvan Vecera 73186ed4cd5SIvan Vecera /* Update DPLL-to-connected-ref phase offsets registers */ 732*b7dbde2bSIvan Vecera rc = zl3073x_ref_phase_offsets_update(zldev, -1); 73386ed4cd5SIvan Vecera if (rc) 73486ed4cd5SIvan Vecera dev_warn(zldev->dev, "Failed to update phase offsets: %pe\n", 73586ed4cd5SIvan Vecera ERR_PTR(rc)); 73675a71eccSIvan Vecera 73775a71eccSIvan Vecera list_for_each_entry(zldpll, &zldev->dplls, list) 73875a71eccSIvan Vecera zl3073x_dpll_changes_check(zldpll); 73975a71eccSIvan Vecera 74075a71eccSIvan Vecera /* Run twice a second */ 74175a71eccSIvan Vecera kthread_queue_delayed_work(zldev->kworker, &zldev->work, 74275a71eccSIvan Vecera msecs_to_jiffies(500)); 74375a71eccSIvan Vecera } 74475a71eccSIvan Vecera 74575a71eccSIvan Vecera static void zl3073x_dev_dpll_fini(void *ptr) 74675a71eccSIvan Vecera { 74775a71eccSIvan Vecera struct zl3073x_dpll *zldpll, *next; 74875a71eccSIvan Vecera struct zl3073x_dev *zldev = ptr; 74975a71eccSIvan Vecera 75075a71eccSIvan Vecera /* Stop monitoring thread */ 75175a71eccSIvan Vecera if (zldev->kworker) { 75275a71eccSIvan Vecera kthread_cancel_delayed_work_sync(&zldev->work); 75375a71eccSIvan Vecera kthread_destroy_worker(zldev->kworker); 75475a71eccSIvan Vecera zldev->kworker = NULL; 75575a71eccSIvan Vecera } 75675a71eccSIvan Vecera 75775a71eccSIvan Vecera /* Release DPLLs */ 75875a71eccSIvan Vecera list_for_each_entry_safe(zldpll, next, &zldev->dplls, list) { 75975a71eccSIvan Vecera zl3073x_dpll_unregister(zldpll); 76075a71eccSIvan Vecera list_del(&zldpll->list); 76175a71eccSIvan Vecera zl3073x_dpll_free(zldpll); 76275a71eccSIvan Vecera } 76375a71eccSIvan Vecera } 76475a71eccSIvan Vecera 76575a71eccSIvan Vecera static int 76675a71eccSIvan Vecera zl3073x_devm_dpll_init(struct zl3073x_dev *zldev, u8 num_dplls) 76775a71eccSIvan Vecera { 76875a71eccSIvan Vecera struct kthread_worker *kworker; 76975a71eccSIvan Vecera struct zl3073x_dpll *zldpll; 77075a71eccSIvan Vecera unsigned int i; 77175a71eccSIvan Vecera int rc; 77275a71eccSIvan Vecera 77375a71eccSIvan Vecera INIT_LIST_HEAD(&zldev->dplls); 77475a71eccSIvan Vecera 77575a71eccSIvan Vecera /* Initialize all DPLLs */ 77675a71eccSIvan Vecera for (i = 0; i < num_dplls; i++) { 77775a71eccSIvan Vecera zldpll = zl3073x_dpll_alloc(zldev, i); 77875a71eccSIvan Vecera if (IS_ERR(zldpll)) { 77975a71eccSIvan Vecera dev_err_probe(zldev->dev, PTR_ERR(zldpll), 78075a71eccSIvan Vecera "Failed to alloc DPLL%u\n", i); 78175a71eccSIvan Vecera rc = PTR_ERR(zldpll); 78275a71eccSIvan Vecera goto error; 78375a71eccSIvan Vecera } 78475a71eccSIvan Vecera 78575a71eccSIvan Vecera rc = zl3073x_dpll_register(zldpll); 78675a71eccSIvan Vecera if (rc) { 78775a71eccSIvan Vecera dev_err_probe(zldev->dev, rc, 78875a71eccSIvan Vecera "Failed to register DPLL%u\n", i); 78975a71eccSIvan Vecera zl3073x_dpll_free(zldpll); 79075a71eccSIvan Vecera goto error; 79175a71eccSIvan Vecera } 79275a71eccSIvan Vecera 79375a71eccSIvan Vecera list_add_tail(&zldpll->list, &zldev->dplls); 79475a71eccSIvan Vecera } 79575a71eccSIvan Vecera 79675a71eccSIvan Vecera /* Perform initial firmware fine phase correction */ 79775a71eccSIvan Vecera rc = zl3073x_dpll_init_fine_phase_adjust(zldev); 79875a71eccSIvan Vecera if (rc) { 79975a71eccSIvan Vecera dev_err_probe(zldev->dev, rc, 80075a71eccSIvan Vecera "Failed to init fine phase correction\n"); 80175a71eccSIvan Vecera goto error; 80275a71eccSIvan Vecera } 80375a71eccSIvan Vecera 80475a71eccSIvan Vecera /* Initialize monitoring thread */ 80575a71eccSIvan Vecera kthread_init_delayed_work(&zldev->work, zl3073x_dev_periodic_work); 80675a71eccSIvan Vecera kworker = kthread_run_worker(0, "zl3073x-%s", dev_name(zldev->dev)); 80775a71eccSIvan Vecera if (IS_ERR(kworker)) { 80875a71eccSIvan Vecera rc = PTR_ERR(kworker); 80975a71eccSIvan Vecera goto error; 81075a71eccSIvan Vecera } 81175a71eccSIvan Vecera 81275a71eccSIvan Vecera zldev->kworker = kworker; 81375a71eccSIvan Vecera kthread_queue_delayed_work(zldev->kworker, &zldev->work, 0); 81475a71eccSIvan Vecera 81575a71eccSIvan Vecera /* Add devres action to release DPLL related resources */ 81675a71eccSIvan Vecera rc = devm_add_action_or_reset(zldev->dev, zl3073x_dev_dpll_fini, zldev); 81775a71eccSIvan Vecera if (rc) 81875a71eccSIvan Vecera goto error; 81975a71eccSIvan Vecera 82075a71eccSIvan Vecera return 0; 82175a71eccSIvan Vecera 82275a71eccSIvan Vecera error: 82375a71eccSIvan Vecera zl3073x_dev_dpll_fini(zldev); 82475a71eccSIvan Vecera 82575a71eccSIvan Vecera return rc; 82675a71eccSIvan Vecera } 82775a71eccSIvan Vecera 8282df8e64eSIvan Vecera /** 82986ed4cd5SIvan Vecera * zl3073x_dev_phase_meas_setup - setup phase offset measurement 83086ed4cd5SIvan Vecera * @zldev: pointer to zl3073x_dev structure 83186ed4cd5SIvan Vecera * @num_channels: number of DPLL channels 83286ed4cd5SIvan Vecera * 83386ed4cd5SIvan Vecera * Enable phase offset measurement block, set measurement averaging factor 83486ed4cd5SIvan Vecera * and enable DPLL-to-its-ref phase measurement for all DPLLs. 83586ed4cd5SIvan Vecera * 83686ed4cd5SIvan Vecera * Returns: 0 on success, <0 on error 83786ed4cd5SIvan Vecera */ 83886ed4cd5SIvan Vecera static int 83986ed4cd5SIvan Vecera zl3073x_dev_phase_meas_setup(struct zl3073x_dev *zldev, int num_channels) 84086ed4cd5SIvan Vecera { 84186ed4cd5SIvan Vecera u8 dpll_meas_ctrl, mask; 84286ed4cd5SIvan Vecera int i, rc; 84386ed4cd5SIvan Vecera 84486ed4cd5SIvan Vecera /* Read DPLL phase measurement control register */ 84586ed4cd5SIvan Vecera rc = zl3073x_read_u8(zldev, ZL_REG_DPLL_MEAS_CTRL, &dpll_meas_ctrl); 84686ed4cd5SIvan Vecera if (rc) 84786ed4cd5SIvan Vecera return rc; 84886ed4cd5SIvan Vecera 84986ed4cd5SIvan Vecera /* Setup phase measurement averaging factor */ 85086ed4cd5SIvan Vecera dpll_meas_ctrl &= ~ZL_DPLL_MEAS_CTRL_AVG_FACTOR; 85186ed4cd5SIvan Vecera dpll_meas_ctrl |= FIELD_PREP(ZL_DPLL_MEAS_CTRL_AVG_FACTOR, 3); 85286ed4cd5SIvan Vecera 85386ed4cd5SIvan Vecera /* Enable DPLL measurement block */ 85486ed4cd5SIvan Vecera dpll_meas_ctrl |= ZL_DPLL_MEAS_CTRL_EN; 85586ed4cd5SIvan Vecera 85686ed4cd5SIvan Vecera /* Update phase measurement control register */ 85786ed4cd5SIvan Vecera rc = zl3073x_write_u8(zldev, ZL_REG_DPLL_MEAS_CTRL, dpll_meas_ctrl); 85886ed4cd5SIvan Vecera if (rc) 85986ed4cd5SIvan Vecera return rc; 86086ed4cd5SIvan Vecera 86186ed4cd5SIvan Vecera /* Enable DPLL-to-connected-ref measurement for each channel */ 86286ed4cd5SIvan Vecera for (i = 0, mask = 0; i < num_channels; i++) 86386ed4cd5SIvan Vecera mask |= BIT(i); 86486ed4cd5SIvan Vecera 86586ed4cd5SIvan Vecera return zl3073x_write_u8(zldev, ZL_REG_DPLL_PHASE_ERR_READ_MASK, mask); 86686ed4cd5SIvan Vecera } 86786ed4cd5SIvan Vecera 86886ed4cd5SIvan Vecera /** 8692df8e64eSIvan Vecera * zl3073x_dev_probe - initialize zl3073x device 8702df8e64eSIvan Vecera * @zldev: pointer to zl3073x device 8712df8e64eSIvan Vecera * @chip_info: chip info based on compatible 8722df8e64eSIvan Vecera * 8732df8e64eSIvan Vecera * Common initialization of zl3073x device structure. 8742df8e64eSIvan Vecera * 8752df8e64eSIvan Vecera * Returns: 0 on success, <0 on error 8762df8e64eSIvan Vecera */ 8772df8e64eSIvan Vecera int zl3073x_dev_probe(struct zl3073x_dev *zldev, 8782df8e64eSIvan Vecera const struct zl3073x_chip_info *chip_info) 8792df8e64eSIvan Vecera { 8802df8e64eSIvan Vecera u16 id, revision, fw_ver; 8812df8e64eSIvan Vecera unsigned int i; 8822df8e64eSIvan Vecera u32 cfg_ver; 8832df8e64eSIvan Vecera int rc; 8842df8e64eSIvan Vecera 8852df8e64eSIvan Vecera /* Read chip ID */ 8862df8e64eSIvan Vecera rc = zl3073x_read_u16(zldev, ZL_REG_ID, &id); 8872df8e64eSIvan Vecera if (rc) 8882df8e64eSIvan Vecera return rc; 8892df8e64eSIvan Vecera 8902df8e64eSIvan Vecera /* Check it matches */ 8912df8e64eSIvan Vecera for (i = 0; i < chip_info->num_ids; i++) { 8922df8e64eSIvan Vecera if (id == chip_info->ids[i]) 8932df8e64eSIvan Vecera break; 8942df8e64eSIvan Vecera } 8952df8e64eSIvan Vecera 8962df8e64eSIvan Vecera if (i == chip_info->num_ids) { 8972df8e64eSIvan Vecera return dev_err_probe(zldev->dev, -ENODEV, 8982df8e64eSIvan Vecera "Unknown or non-match chip ID: 0x%0x\n", 8992df8e64eSIvan Vecera id); 9002df8e64eSIvan Vecera } 9012df8e64eSIvan Vecera 9022df8e64eSIvan Vecera /* Read revision, firmware version and custom config version */ 9032df8e64eSIvan Vecera rc = zl3073x_read_u16(zldev, ZL_REG_REVISION, &revision); 9042df8e64eSIvan Vecera if (rc) 9052df8e64eSIvan Vecera return rc; 9062df8e64eSIvan Vecera rc = zl3073x_read_u16(zldev, ZL_REG_FW_VER, &fw_ver); 9072df8e64eSIvan Vecera if (rc) 9082df8e64eSIvan Vecera return rc; 9092df8e64eSIvan Vecera rc = zl3073x_read_u32(zldev, ZL_REG_CUSTOM_CONFIG_VER, &cfg_ver); 9102df8e64eSIvan Vecera if (rc) 9112df8e64eSIvan Vecera return rc; 9122df8e64eSIvan Vecera 9132df8e64eSIvan Vecera dev_dbg(zldev->dev, "ChipID(%X), ChipRev(%X), FwVer(%u)\n", id, 9142df8e64eSIvan Vecera revision, fw_ver); 9152df8e64eSIvan Vecera dev_dbg(zldev->dev, "Custom config version: %lu.%lu.%lu.%lu\n", 9162df8e64eSIvan Vecera FIELD_GET(GENMASK(31, 24), cfg_ver), 9172df8e64eSIvan Vecera FIELD_GET(GENMASK(23, 16), cfg_ver), 9182df8e64eSIvan Vecera FIELD_GET(GENMASK(15, 8), cfg_ver), 9192df8e64eSIvan Vecera FIELD_GET(GENMASK(7, 0), cfg_ver)); 9202df8e64eSIvan Vecera 9212df8e64eSIvan Vecera /* Generate random clock ID as the device has not such property that 9222df8e64eSIvan Vecera * could be used for this purpose. A user can later change this value 9232df8e64eSIvan Vecera * using devlink. 9242df8e64eSIvan Vecera */ 9252df8e64eSIvan Vecera zldev->clock_id = get_random_u64(); 9262df8e64eSIvan Vecera 9272df8e64eSIvan Vecera /* Initialize mutex for operations where multiple reads, writes 9282df8e64eSIvan Vecera * and/or polls are required to be done atomically. 9292df8e64eSIvan Vecera */ 9302df8e64eSIvan Vecera rc = devm_mutex_init(zldev->dev, &zldev->multiop_lock); 9312df8e64eSIvan Vecera if (rc) 9322df8e64eSIvan Vecera return dev_err_probe(zldev->dev, rc, 9332df8e64eSIvan Vecera "Failed to initialize mutex\n"); 9342df8e64eSIvan Vecera 935b7d907d1SIvan Vecera /* Fetch device state */ 936b7d907d1SIvan Vecera rc = zl3073x_dev_state_fetch(zldev); 937b7d907d1SIvan Vecera if (rc) 938b7d907d1SIvan Vecera return rc; 939b7d907d1SIvan Vecera 94086ed4cd5SIvan Vecera /* Setup phase offset measurement block */ 94186ed4cd5SIvan Vecera rc = zl3073x_dev_phase_meas_setup(zldev, chip_info->num_channels); 94286ed4cd5SIvan Vecera if (rc) 94386ed4cd5SIvan Vecera return dev_err_probe(zldev->dev, rc, 94486ed4cd5SIvan Vecera "Failed to setup phase measurement\n"); 94586ed4cd5SIvan Vecera 94675a71eccSIvan Vecera /* Register DPLL channels */ 94775a71eccSIvan Vecera rc = zl3073x_devm_dpll_init(zldev, chip_info->num_channels); 94875a71eccSIvan Vecera if (rc) 94975a71eccSIvan Vecera return rc; 95075a71eccSIvan Vecera 9512df8e64eSIvan Vecera /* Register the devlink instance and parameters */ 9522df8e64eSIvan Vecera rc = zl3073x_devlink_register(zldev); 9532df8e64eSIvan Vecera if (rc) 9542df8e64eSIvan Vecera return dev_err_probe(zldev->dev, rc, 9552df8e64eSIvan Vecera "Failed to register devlink instance\n"); 9562df8e64eSIvan Vecera 9572df8e64eSIvan Vecera return 0; 9582df8e64eSIvan Vecera } 9592df8e64eSIvan Vecera EXPORT_SYMBOL_NS_GPL(zl3073x_dev_probe, "ZL3073X"); 9602df8e64eSIvan Vecera 9612df8e64eSIvan Vecera MODULE_AUTHOR("Ivan Vecera <ivecera@redhat.com>"); 9622df8e64eSIvan Vecera MODULE_DESCRIPTION("Microchip ZL3073x core driver"); 9632df8e64eSIvan Vecera MODULE_LICENSE("GPL"); 964