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" 20*75a71eccSIvan 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 672*75a71eccSIvan Vecera static void 673*75a71eccSIvan Vecera zl3073x_dev_periodic_work(struct kthread_work *work) 674*75a71eccSIvan Vecera { 675*75a71eccSIvan Vecera struct zl3073x_dev *zldev = container_of(work, struct zl3073x_dev, 676*75a71eccSIvan Vecera work.work); 677*75a71eccSIvan Vecera struct zl3073x_dpll *zldpll; 678*75a71eccSIvan Vecera 679*75a71eccSIvan Vecera list_for_each_entry(zldpll, &zldev->dplls, list) 680*75a71eccSIvan Vecera zl3073x_dpll_changes_check(zldpll); 681*75a71eccSIvan Vecera 682*75a71eccSIvan Vecera /* Run twice a second */ 683*75a71eccSIvan Vecera kthread_queue_delayed_work(zldev->kworker, &zldev->work, 684*75a71eccSIvan Vecera msecs_to_jiffies(500)); 685*75a71eccSIvan Vecera } 686*75a71eccSIvan Vecera 687*75a71eccSIvan Vecera static void zl3073x_dev_dpll_fini(void *ptr) 688*75a71eccSIvan Vecera { 689*75a71eccSIvan Vecera struct zl3073x_dpll *zldpll, *next; 690*75a71eccSIvan Vecera struct zl3073x_dev *zldev = ptr; 691*75a71eccSIvan Vecera 692*75a71eccSIvan Vecera /* Stop monitoring thread */ 693*75a71eccSIvan Vecera if (zldev->kworker) { 694*75a71eccSIvan Vecera kthread_cancel_delayed_work_sync(&zldev->work); 695*75a71eccSIvan Vecera kthread_destroy_worker(zldev->kworker); 696*75a71eccSIvan Vecera zldev->kworker = NULL; 697*75a71eccSIvan Vecera } 698*75a71eccSIvan Vecera 699*75a71eccSIvan Vecera /* Release DPLLs */ 700*75a71eccSIvan Vecera list_for_each_entry_safe(zldpll, next, &zldev->dplls, list) { 701*75a71eccSIvan Vecera zl3073x_dpll_unregister(zldpll); 702*75a71eccSIvan Vecera list_del(&zldpll->list); 703*75a71eccSIvan Vecera zl3073x_dpll_free(zldpll); 704*75a71eccSIvan Vecera } 705*75a71eccSIvan Vecera } 706*75a71eccSIvan Vecera 707*75a71eccSIvan Vecera static int 708*75a71eccSIvan Vecera zl3073x_devm_dpll_init(struct zl3073x_dev *zldev, u8 num_dplls) 709*75a71eccSIvan Vecera { 710*75a71eccSIvan Vecera struct kthread_worker *kworker; 711*75a71eccSIvan Vecera struct zl3073x_dpll *zldpll; 712*75a71eccSIvan Vecera unsigned int i; 713*75a71eccSIvan Vecera int rc; 714*75a71eccSIvan Vecera 715*75a71eccSIvan Vecera INIT_LIST_HEAD(&zldev->dplls); 716*75a71eccSIvan Vecera 717*75a71eccSIvan Vecera /* Initialize all DPLLs */ 718*75a71eccSIvan Vecera for (i = 0; i < num_dplls; i++) { 719*75a71eccSIvan Vecera zldpll = zl3073x_dpll_alloc(zldev, i); 720*75a71eccSIvan Vecera if (IS_ERR(zldpll)) { 721*75a71eccSIvan Vecera dev_err_probe(zldev->dev, PTR_ERR(zldpll), 722*75a71eccSIvan Vecera "Failed to alloc DPLL%u\n", i); 723*75a71eccSIvan Vecera rc = PTR_ERR(zldpll); 724*75a71eccSIvan Vecera goto error; 725*75a71eccSIvan Vecera } 726*75a71eccSIvan Vecera 727*75a71eccSIvan Vecera rc = zl3073x_dpll_register(zldpll); 728*75a71eccSIvan Vecera if (rc) { 729*75a71eccSIvan Vecera dev_err_probe(zldev->dev, rc, 730*75a71eccSIvan Vecera "Failed to register DPLL%u\n", i); 731*75a71eccSIvan Vecera zl3073x_dpll_free(zldpll); 732*75a71eccSIvan Vecera goto error; 733*75a71eccSIvan Vecera } 734*75a71eccSIvan Vecera 735*75a71eccSIvan Vecera list_add_tail(&zldpll->list, &zldev->dplls); 736*75a71eccSIvan Vecera } 737*75a71eccSIvan Vecera 738*75a71eccSIvan Vecera /* Perform initial firmware fine phase correction */ 739*75a71eccSIvan Vecera rc = zl3073x_dpll_init_fine_phase_adjust(zldev); 740*75a71eccSIvan Vecera if (rc) { 741*75a71eccSIvan Vecera dev_err_probe(zldev->dev, rc, 742*75a71eccSIvan Vecera "Failed to init fine phase correction\n"); 743*75a71eccSIvan Vecera goto error; 744*75a71eccSIvan Vecera } 745*75a71eccSIvan Vecera 746*75a71eccSIvan Vecera /* Initialize monitoring thread */ 747*75a71eccSIvan Vecera kthread_init_delayed_work(&zldev->work, zl3073x_dev_periodic_work); 748*75a71eccSIvan Vecera kworker = kthread_run_worker(0, "zl3073x-%s", dev_name(zldev->dev)); 749*75a71eccSIvan Vecera if (IS_ERR(kworker)) { 750*75a71eccSIvan Vecera rc = PTR_ERR(kworker); 751*75a71eccSIvan Vecera goto error; 752*75a71eccSIvan Vecera } 753*75a71eccSIvan Vecera 754*75a71eccSIvan Vecera zldev->kworker = kworker; 755*75a71eccSIvan Vecera kthread_queue_delayed_work(zldev->kworker, &zldev->work, 0); 756*75a71eccSIvan Vecera 757*75a71eccSIvan Vecera /* Add devres action to release DPLL related resources */ 758*75a71eccSIvan Vecera rc = devm_add_action_or_reset(zldev->dev, zl3073x_dev_dpll_fini, zldev); 759*75a71eccSIvan Vecera if (rc) 760*75a71eccSIvan Vecera goto error; 761*75a71eccSIvan Vecera 762*75a71eccSIvan Vecera return 0; 763*75a71eccSIvan Vecera 764*75a71eccSIvan Vecera error: 765*75a71eccSIvan Vecera zl3073x_dev_dpll_fini(zldev); 766*75a71eccSIvan Vecera 767*75a71eccSIvan Vecera return rc; 768*75a71eccSIvan Vecera } 769*75a71eccSIvan Vecera 7702df8e64eSIvan Vecera /** 7712df8e64eSIvan Vecera * zl3073x_dev_probe - initialize zl3073x device 7722df8e64eSIvan Vecera * @zldev: pointer to zl3073x device 7732df8e64eSIvan Vecera * @chip_info: chip info based on compatible 7742df8e64eSIvan Vecera * 7752df8e64eSIvan Vecera * Common initialization of zl3073x device structure. 7762df8e64eSIvan Vecera * 7772df8e64eSIvan Vecera * Returns: 0 on success, <0 on error 7782df8e64eSIvan Vecera */ 7792df8e64eSIvan Vecera int zl3073x_dev_probe(struct zl3073x_dev *zldev, 7802df8e64eSIvan Vecera const struct zl3073x_chip_info *chip_info) 7812df8e64eSIvan Vecera { 7822df8e64eSIvan Vecera u16 id, revision, fw_ver; 7832df8e64eSIvan Vecera unsigned int i; 7842df8e64eSIvan Vecera u32 cfg_ver; 7852df8e64eSIvan Vecera int rc; 7862df8e64eSIvan Vecera 7872df8e64eSIvan Vecera /* Read chip ID */ 7882df8e64eSIvan Vecera rc = zl3073x_read_u16(zldev, ZL_REG_ID, &id); 7892df8e64eSIvan Vecera if (rc) 7902df8e64eSIvan Vecera return rc; 7912df8e64eSIvan Vecera 7922df8e64eSIvan Vecera /* Check it matches */ 7932df8e64eSIvan Vecera for (i = 0; i < chip_info->num_ids; i++) { 7942df8e64eSIvan Vecera if (id == chip_info->ids[i]) 7952df8e64eSIvan Vecera break; 7962df8e64eSIvan Vecera } 7972df8e64eSIvan Vecera 7982df8e64eSIvan Vecera if (i == chip_info->num_ids) { 7992df8e64eSIvan Vecera return dev_err_probe(zldev->dev, -ENODEV, 8002df8e64eSIvan Vecera "Unknown or non-match chip ID: 0x%0x\n", 8012df8e64eSIvan Vecera id); 8022df8e64eSIvan Vecera } 8032df8e64eSIvan Vecera 8042df8e64eSIvan Vecera /* Read revision, firmware version and custom config version */ 8052df8e64eSIvan Vecera rc = zl3073x_read_u16(zldev, ZL_REG_REVISION, &revision); 8062df8e64eSIvan Vecera if (rc) 8072df8e64eSIvan Vecera return rc; 8082df8e64eSIvan Vecera rc = zl3073x_read_u16(zldev, ZL_REG_FW_VER, &fw_ver); 8092df8e64eSIvan Vecera if (rc) 8102df8e64eSIvan Vecera return rc; 8112df8e64eSIvan Vecera rc = zl3073x_read_u32(zldev, ZL_REG_CUSTOM_CONFIG_VER, &cfg_ver); 8122df8e64eSIvan Vecera if (rc) 8132df8e64eSIvan Vecera return rc; 8142df8e64eSIvan Vecera 8152df8e64eSIvan Vecera dev_dbg(zldev->dev, "ChipID(%X), ChipRev(%X), FwVer(%u)\n", id, 8162df8e64eSIvan Vecera revision, fw_ver); 8172df8e64eSIvan Vecera dev_dbg(zldev->dev, "Custom config version: %lu.%lu.%lu.%lu\n", 8182df8e64eSIvan Vecera FIELD_GET(GENMASK(31, 24), cfg_ver), 8192df8e64eSIvan Vecera FIELD_GET(GENMASK(23, 16), cfg_ver), 8202df8e64eSIvan Vecera FIELD_GET(GENMASK(15, 8), cfg_ver), 8212df8e64eSIvan Vecera FIELD_GET(GENMASK(7, 0), cfg_ver)); 8222df8e64eSIvan Vecera 8232df8e64eSIvan Vecera /* Generate random clock ID as the device has not such property that 8242df8e64eSIvan Vecera * could be used for this purpose. A user can later change this value 8252df8e64eSIvan Vecera * using devlink. 8262df8e64eSIvan Vecera */ 8272df8e64eSIvan Vecera zldev->clock_id = get_random_u64(); 8282df8e64eSIvan Vecera 8292df8e64eSIvan Vecera /* Initialize mutex for operations where multiple reads, writes 8302df8e64eSIvan Vecera * and/or polls are required to be done atomically. 8312df8e64eSIvan Vecera */ 8322df8e64eSIvan Vecera rc = devm_mutex_init(zldev->dev, &zldev->multiop_lock); 8332df8e64eSIvan Vecera if (rc) 8342df8e64eSIvan Vecera return dev_err_probe(zldev->dev, rc, 8352df8e64eSIvan Vecera "Failed to initialize mutex\n"); 8362df8e64eSIvan Vecera 837b7d907d1SIvan Vecera /* Fetch device state */ 838b7d907d1SIvan Vecera rc = zl3073x_dev_state_fetch(zldev); 839b7d907d1SIvan Vecera if (rc) 840b7d907d1SIvan Vecera return rc; 841b7d907d1SIvan Vecera 842*75a71eccSIvan Vecera /* Register DPLL channels */ 843*75a71eccSIvan Vecera rc = zl3073x_devm_dpll_init(zldev, chip_info->num_channels); 844*75a71eccSIvan Vecera if (rc) 845*75a71eccSIvan Vecera return rc; 846*75a71eccSIvan Vecera 8472df8e64eSIvan Vecera /* Register the devlink instance and parameters */ 8482df8e64eSIvan Vecera rc = zl3073x_devlink_register(zldev); 8492df8e64eSIvan Vecera if (rc) 8502df8e64eSIvan Vecera return dev_err_probe(zldev->dev, rc, 8512df8e64eSIvan Vecera "Failed to register devlink instance\n"); 8522df8e64eSIvan Vecera 8532df8e64eSIvan Vecera return 0; 8542df8e64eSIvan Vecera } 8552df8e64eSIvan Vecera EXPORT_SYMBOL_NS_GPL(zl3073x_dev_probe, "ZL3073X"); 8562df8e64eSIvan Vecera 8572df8e64eSIvan Vecera MODULE_AUTHOR("Ivan Vecera <ivecera@redhat.com>"); 8582df8e64eSIvan Vecera MODULE_DESCRIPTION("Microchip ZL3073x core driver"); 8592df8e64eSIvan Vecera MODULE_LICENSE("GPL"); 860