linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/2] clk: ad9545: Add support
@ 2021-06-14  7:07 alexandru.tachici
  2021-06-14  7:07 ` [PATCH v2 1/2] " alexandru.tachici
  2021-06-14  7:07 ` [PATCH v2 2/2] dt-bindings: clock: ad9545: Add documentation alexandru.tachici
  0 siblings, 2 replies; 9+ messages in thread
From: alexandru.tachici @ 2021-06-14  7:07 UTC (permalink / raw)
  To: linux-clk, linux-kernel, devicetree
  Cc: robh+dt, sboyd, mturquette, petre.minciunescu, Alexandru Tachici

From: Alexandru Tachici <alexandru.tachici@analog.com>

Add support for AD9545 Quad Input, 10-Output, Dual DPLL/IEEE 1588,
1 pps Synchronizer and Jitter Cleaner.

At the core of the device there are PLL blocks. Each block consists
of one DPLL and one APLL. The DPLL can be fed timestamps from one of
the 4 reference input dividers or one of the two auxiliary NCOs.

The APLL takes the output of the DPLL and up-converts this
frequency to 1.2-2.0 GHZ. First 6 output dividers are receiving
clock from APLL0 and last 4 outputs are receiving clock from APLL1.

Current approach is to register under common clock framework,
depending whether they are mentioned in the device-tree,
any of the used references input dividers, the two auxiliary
NCOs, PLL blocks, output dividers.

A clock tree example:
Ref-B
  Ref-B-Div
    PLL0
      Q0C-div
    PLL1
      Q1A-div
      Q1B-div

Alexandru Tachici (2):
  clk: ad9545: Add support
  dt-bindings: clock: ad9545: Add documentation

Changelog v1 -> v2:
- allow uHz DPLL loop bandwidth in DT
- allow user to set different tub fill/drain rates per DPLL from DT
for improved locking detection
- added reference priorities, DPLLs now can have multiple parents selected based on
the validity of the reference in question and priority
- added fast ACQ process that can be configured in the DT
- fixed DT bindings errors
- added support for system clock compensation

 .../devicetree/bindings/clock/clk-ad9545.yaml |  556 ++++
 drivers/clk/Kconfig                           |    6 +
 drivers/clk/Makefile                          |    1 +
 drivers/clk/adi/Kconfig                       |   29 +
 drivers/clk/adi/Makefile                      |    9 +
 drivers/clk/adi/clk-ad9545-i2c.c              |   62 +
 drivers/clk/adi/clk-ad9545-spi.c              |   76 +
 drivers/clk/adi/clk-ad9545.c                  | 2428 +++++++++++++++++
 drivers/clk/adi/clk-ad9545.h                  |   16 +
 include/dt-bindings/clock/ad9545.h            |   69 +
 10 files changed, 3252 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/clk-ad9545.yaml
 create mode 100644 drivers/clk/adi/Kconfig
 create mode 100644 drivers/clk/adi/Makefile
 create mode 100644 drivers/clk/adi/clk-ad9545-i2c.c
 create mode 100644 drivers/clk/adi/clk-ad9545-spi.c
 create mode 100644 drivers/clk/adi/clk-ad9545.c
 create mode 100644 drivers/clk/adi/clk-ad9545.h
 create mode 100644 include/dt-bindings/clock/ad9545.h

--
2.25.1

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 1/2] clk: ad9545: Add support
  2021-06-14  7:07 [PATCH v2 0/2] clk: ad9545: Add support alexandru.tachici
@ 2021-06-14  7:07 ` alexandru.tachici
  2021-06-14  7:07 ` [PATCH v2 2/2] dt-bindings: clock: ad9545: Add documentation alexandru.tachici
  1 sibling, 0 replies; 9+ messages in thread
From: alexandru.tachici @ 2021-06-14  7:07 UTC (permalink / raw)
  To: linux-clk, linux-kernel, devicetree
  Cc: robh+dt, sboyd, mturquette, petre.minciunescu, Alexandru Tachici

From: Alexandru Tachici <alexandru.tachici@analog.com>

Add support for AD9545 Quad Input, 10-Output, Dual DPLL/IEEE 1588,
1 pps Synchronizer and Jitter Cleaner.

Signed-off-by: Alexandru Tachici <alexandru.tachici@analog.com>
---
 drivers/clk/Kconfig              |    6 +
 drivers/clk/Makefile             |    1 +
 drivers/clk/adi/Kconfig          |   29 +
 drivers/clk/adi/Makefile         |    9 +
 drivers/clk/adi/clk-ad9545-i2c.c |   62 +
 drivers/clk/adi/clk-ad9545-spi.c |   76 +
 drivers/clk/adi/clk-ad9545.c     | 2428 ++++++++++++++++++++++++++++++
 drivers/clk/adi/clk-ad9545.h     |   16 +
 8 files changed, 2627 insertions(+)
 create mode 100644 drivers/clk/adi/Kconfig
 create mode 100644 drivers/clk/adi/Makefile
 create mode 100644 drivers/clk/adi/clk-ad9545-i2c.c
 create mode 100644 drivers/clk/adi/clk-ad9545-spi.c
 create mode 100644 drivers/clk/adi/clk-ad9545.c
 create mode 100644 drivers/clk/adi/clk-ad9545.h

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index e80918be8e9c..c39dfb6a6b66 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -38,6 +38,11 @@ menuconfig COMMON_CLK
 
 if COMMON_CLK
 
+config COMMON_CLK_ADI
+	def_bool COMMON_CLK
+	help
+	  Support for Analog Devices clock providers.
+
 config COMMON_CLK_WM831X
 	tristate "Clock driver for WM831x/2x PMICs"
 	depends on MFD_WM831X
@@ -377,6 +382,7 @@ config COMMON_CLK_K210
 	  Support for the Canaan Kendryte K210 RISC-V SoC clocks.
 
 source "drivers/clk/actions/Kconfig"
+source "drivers/clk/adi/Kconfig"
 source "drivers/clk/analogbits/Kconfig"
 source "drivers/clk/baikal-t1/Kconfig"
 source "drivers/clk/bcm/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 5f06879d7fe9..181064b6e593 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -71,6 +71,7 @@ obj-$(CONFIG_COMMON_CLK_XGENE)		+= clk-xgene.o
 
 # please keep this section sorted lexicographically by directory path name
 obj-y					+= actions/
+obj-$(CONFIG_COMMON_CLK_ADI)		+= adi/
 obj-y					+= analogbits/
 obj-$(CONFIG_COMMON_CLK_AT91)		+= at91/
 obj-$(CONFIG_ARCH_ARTPEC)		+= axis/
diff --git a/drivers/clk/adi/Kconfig b/drivers/clk/adi/Kconfig
new file mode 100644
index 000000000000..768b8227f336
--- /dev/null
+++ b/drivers/clk/adi/Kconfig
@@ -0,0 +1,29 @@
+#
+# Analog Devices Clock Drivers
+#
+# When adding new entries keep the list in alphabetical order
+
+menu "Analog Devices Clock Drivers"
+
+config COMMON_CLK_AD9545
+	tristate
+
+config COMMON_CLK_AD9545_I2C
+	tristate "Analog Devices AD9545 via I2C"
+	depends on REGMAP_I2C
+	select COMMON_CLK_AD9545
+	help
+	  Say yes here to build support for Analog Devices AD9545
+	  Quad Input, 10-Output, Dual DPLL/IEEE 1588,
+	  1 pps Synchronizer and Jitter Cleaner via I2C
+
+config COMMON_CLK_AD9545_SPI
+	tristate "Analog Devices AD9545 via SPI"
+	depends on REGMAP_SPI
+	select COMMON_CLK_AD9545
+	help
+	  Say yes here to build support for Analog Devices AD9545
+	  Quad Input, 10-Output, Dual DPLL/IEEE 1588,
+	  1 pps Synchronizer and Jitter Cleaner via SPI
+
+endmenu
diff --git a/drivers/clk/adi/Makefile b/drivers/clk/adi/Makefile
new file mode 100644
index 000000000000..7ba1fded3013
--- /dev/null
+++ b/drivers/clk/adi/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+#
+# Makefile for AD9545 Network Clock Generator/Synchronizer
+#
+
+# When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_COMMON_CLK_AD9545) += clk-ad9545.o
+obj-$(CONFIG_COMMON_CLK_AD9545_I2C) += clk-ad9545-i2c.o
+obj-$(CONFIG_COMMON_CLK_AD9545_SPI) += clk-ad9545-spi.o
diff --git a/drivers/clk/adi/clk-ad9545-i2c.c b/drivers/clk/adi/clk-ad9545-i2c.c
new file mode 100644
index 000000000000..c85326b3cdd2
--- /dev/null
+++ b/drivers/clk/adi/clk-ad9545-i2c.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * AD9545 Network Clock Generator/Synchronizer
+ *
+ * Copyright 2020 Analog Devices Inc.
+ */
+
+#include "clk-ad9545.h"
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+static const struct regmap_config ad9545_regmap_config = {
+	.reg_bits = 16,
+	.val_bits = 8,
+	.max_register = 0x3A3B,
+	.use_single_read = true,
+	.use_single_write = true,
+};
+
+static int ad9545_i2c_probe(struct i2c_client *client)
+{
+	struct regmap *regmap;
+
+	regmap = devm_regmap_init_i2c(client, &ad9545_regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(&client->dev, "devm_regmap_init_i2c failed!\n");
+		return PTR_ERR(regmap);
+	}
+
+	return ad9545_probe(&client->dev, regmap);
+}
+
+static const struct of_device_id ad9545_i2c_of_match[] = {
+	{ .compatible = "adi,ad9545" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ad9545_i2c_of_match);
+
+static const struct i2c_device_id ad9545_i2c_id[] = {
+	{"ad9545"},
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ad9545_i2c_id);
+
+static struct i2c_driver ad9545_i2c_driver = {
+	.driver = {
+		.name	= "ad9545",
+		.of_match_table = ad9545_i2c_of_match,
+	},
+	.probe_new	= ad9545_i2c_probe,
+	.id_table	= ad9545_i2c_id,
+};
+module_i2c_driver(ad9545_i2c_driver);
+
+MODULE_AUTHOR("Alexandru Tachici <alexandru.tachici@analog.com>");
+MODULE_DESCRIPTION("Analog Devices AD9545 I2C");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/clk/adi/clk-ad9545-spi.c b/drivers/clk/adi/clk-ad9545-spi.c
new file mode 100644
index 000000000000..b0f9f59e6dea
--- /dev/null
+++ b/drivers/clk/adi/clk-ad9545-spi.c
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * AD9545 Network Clock Generator/Synchronizer
+ *
+ * Copyright 2020 Analog Devices Inc.
+ */
+
+#include "clk-ad9545.h"
+#include <linux/bitfield.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/iio/iio.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+
+#define AD9545_CONFIG_0			0x0000
+
+#define AD9545_4WIRE_SPI		0x3
+#define AD9545_4WIRE_SPI_MSK		GENMASK(4, 3)
+
+static const struct regmap_config ad9545_regmap_config = {
+	.reg_bits = 16,
+	.val_bits = 8,
+	.max_register = 0x3A3B,
+	.use_single_read = true,
+	.use_single_write = true,
+};
+
+static int ad9545_spi_probe(struct spi_device *spi)
+{
+	struct regmap *regmap;
+	int ret;
+
+	regmap = devm_regmap_init_spi(spi, &ad9545_regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(&spi->dev, "devm_regmap_init_spi failed!\n");
+		return PTR_ERR(regmap);
+	}
+
+	if (!(spi->mode & SPI_3WIRE)) {
+		ret = regmap_write(regmap, AD9545_CONFIG_0,
+				   FIELD_PREP(AD9545_4WIRE_SPI_MSK, AD9545_4WIRE_SPI));
+		if (ret < 0)
+			return ret;
+	}
+
+	return ad9545_probe(&spi->dev, regmap);
+}
+
+static const struct of_device_id ad9545_spi_of_match[] = {
+	{ .compatible = "adi,ad9545" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ad9545_spi_of_match);
+
+static const struct spi_device_id ad9545_spi_id[] = {
+	{"ad9545", 0},
+	{ }
+};
+MODULE_DEVICE_TABLE(spi, ad9545_spi_id);
+
+static struct spi_driver ad9545_spi_driver = {
+	.driver = {
+		.name	= "ad9545",
+		.of_match_table = ad9545_spi_of_match,
+	},
+	.probe		= ad9545_spi_probe,
+	.id_table	= ad9545_spi_id,
+};
+module_spi_driver(ad9545_spi_driver);
+
+MODULE_AUTHOR("Alexandru Tachici <alexandru.tachici@analog.com>");
+MODULE_DESCRIPTION("Analog Devices AD9545 SPI");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/clk/adi/clk-ad9545.c b/drivers/clk/adi/clk-ad9545.c
new file mode 100644
index 000000000000..b678b11fcd15
--- /dev/null
+++ b/drivers/clk/adi/clk-ad9545.c
@@ -0,0 +1,2428 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * AD9545 Network Clock Generator/Synchronizer
+ *
+ * Copyright 2020 Analog Devices Inc.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/rational.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#include <dt-bindings/clock/ad9545.h>
+
+#define AD9545_CONFIG_0			0x0000
+#define AD9545_PRODUCT_ID_LOW		0x0004
+#define AD9545_PRODUCT_ID_HIGH		0x0005
+#define AD9545_IO_UPDATE		0x000F
+#define AD9545_M0_PIN			0x0102
+#define AD9545_CHIP_ID			0x0121
+#define AD9545_SYS_CLK_FB_DIV		0x0200
+#define AD9545_SYS_CLK_INPUT		0x0201
+#define AD9545_SYS_CLK_REF_FREQ		0x0202
+#define AD9545_SYS_STABILITY_T		0x0207
+#define AD9545_COMPENSATE_TDCS		0x0280
+#define AD9545_COMPENSATE_DPLL		0x0282
+#define AD9545_AUX_DPLL_CHANGE_LIMIT	0x0283
+#define AD9545_AUX_DPLL_SOURCE		0x0284
+#define AD9545_AUX_DPLL_LOOP_BW		0x0285
+#define AD9545_REF_A_CTRL		0x0300
+#define AD9545_REF_A_RDIV		0x0400
+#define AD9545_REF_A_PERIOD		0x0404
+#define AD9545_REF_A_OFFSET_LIMIT	0x040C
+#define AD9545_REF_A_MONITOR_HYST	0x040F
+#define AD9545_PHASE_LOCK_THRESH	0x0800
+#define AD9545_PHASE_LOCK_FILL_RATE	0x0803
+#define AD9545_PHASE_LOCK_DRAIN_RATE	0x0804
+#define AD9545_FREQ_LOCK_THRESH		0x0805
+#define AD9545_FREQ_LOCK_FILL_RATE	0x0808
+#define AD9545_FREQ_LOCK_DRAIN_RATE	0x0809
+#define AD9545_DPLL0_FTW		0x1000
+#define AD9545_DRIVER_0A_CONF		0x10D7
+#define AD9545_SYNC_CTRL0		0x10DB
+#define AD9545_APLL0_M_DIV		0x1081
+#define AD9545_Q0A_DIV			0x1100
+#define AD9545_Q0A_PHASE		0x1104
+#define AD9545_Q0A_PHASE_CONF		0x1108
+#define AD9545_DPLL0_EN			0x1200
+#define AD9545_DPLL0_SOURCE		0x1201
+#define AD9545_DPLL0_LOOP_BW		0x1204
+#define AD9545_DPLL0_N_DIV		0x120C
+#define AD9545_DPLL0_FRAC		0x1210
+#define AD9545_DPLL0_MOD		0x1213
+#define AD9545_DPLL0_FAST_L1		0x1216
+#define AD9545_DPLL0_FAST_L2		0x1217
+#define AD9545_DRIVER_1A_CONF		0x14D7
+#define AD9545_Q1A_DIV			0x1500
+#define AD9545_Q1A_PHASE		0x1504
+#define AD9545_Q1A_PHASE_CONF		0x1508
+#define AD9545_CALIB_CLK		0x2000
+#define AD9545_POWER_DOWN_REF		0x2001
+#define AD9545_PWR_CALIB_CH0		0x2100
+#define AD9545_CTRL_CH0			0x2101
+#define AD9545_DIV_OPS_Q0A		0x2102
+#define AD9545_DPLL0_MODE		0x2105
+#define AD9545_DPLL0_FAST_MODE		0x2106
+#define AD9545_DIV_OPS_Q1A		0x2202
+#define AD9545_NCO0_FREQ		0x2805
+#define AD9545_TDC0_DIV			0x2A00
+#define AD9545_TDC0_PERIOD		0x2A01
+#define AD9545_PLL_STATUS		0x3001
+#define AD9545_MISC			0x3002
+#define AD9545_REFA_STATUS		0x3005
+#define AD9545_PLL0_STATUS		0x3100
+
+#define AD9545_REF_CTRL_DIF_MSK			GENMASK(3, 2)
+#define AD9545_REF_CTRL_REFA_MSK		GENMASK(5, 4)
+#define AD9545_REF_CTRL_REFAA_MSK		GENMASK(7, 6)
+
+#define AD9545_UPDATE_REGS			0x1
+#define AD9545_RESET_REGS			0x81
+
+#define AD9545_MX_PIN(x)			(AD9545_M0_PIN + (x))
+
+#define AD9545_SYNC_CTRLX(x)			(AD9545_SYNC_CTRL0 + ((x) * 0x400))
+#define AD9545_REF_X_RDIV(x)			(AD9545_REF_A_RDIV + ((x) * 0x20))
+#define AD9545_REF_X_PERIOD(x)			(AD9545_REF_A_PERIOD + ((x) * 0x20))
+#define AD9545_REF_X_OFFSET_LIMIT(x)		(AD9545_REF_A_OFFSET_LIMIT + ((x) * 0x20))
+#define AD9545_REF_X_MONITOR_HYST(x)		(AD9545_REF_A_MONITOR_HYST + ((x) * 0x20))
+#define AD9545_REF_X_PHASE_LOCK_FILL(x)		(AD9545_PHASE_LOCK_FILL_RATE + ((x) * 0x20))
+#define AD9545_REF_X_PHASE_LOCK_DRAIN(x)	(AD9545_PHASE_LOCK_DRAIN_RATE + ((x) * 0x20))
+#define AD9545_REF_X_FREQ_LOCK_FILL(x)		(AD9545_FREQ_LOCK_FILL_RATE + ((x) * 0x20))
+#define AD9545_REF_X_FREQ_LOCK_DRAIN(x)		(AD9545_FREQ_LOCK_DRAIN_RATE + ((x) * 0x20))
+
+#define AD9545_SOURCEX_PHASE_THRESH(x)		(AD9545_PHASE_LOCK_THRESH + ((x) * 0x20))
+#define AD9545_SOURCEX_FREQ_THRESH(x)		(AD9545_FREQ_LOCK_THRESH + ((x) * 0x20))
+#define AD9545_NCOX_PHASE_THRESH(x)		(AD9545_SOURCEX_PHASE_THRESH((x) + 4))
+#define AD9545_NCOX_FREQ_THRESH(x)		(AD9545_SOURCEX_FREQ_THRESH((x) + 4))
+
+#define AD9545_APLLX_M_DIV(x)			(AD9545_APLL0_M_DIV + ((x) * 0x400))
+
+#define AD9545_Q0_DIV(x)			(AD9545_Q0A_DIV + ((x) * 0x9))
+#define AD9545_Q1_DIV(x)			(AD9545_Q1A_DIV + ((x) * 0x9))
+#define AD9545_QX_DIV(x) ({					\
+	typeof(x) x_ = (x);					\
+								\
+	(x_ > 5) ? AD9545_Q1_DIV(x_ - 6) : AD9545_Q0_DIV(x_);	\
+})
+
+#define AD9545_Q0_PHASE(x)			(AD9545_Q0A_PHASE + ((x) * 0x9))
+#define AD9545_Q1_PHASE(x)			(AD9545_Q1A_PHASE + ((x) * 0x9))
+#define AD9545_QX_PHASE(x) ({						\
+	typeof(x) x_ = (x);						\
+									\
+	(x_ > 5) ? AD9545_Q1_PHASE(x_ - 6) : AD9545_Q0_PHASE(x_);	\
+})
+
+#define AD9545_Q0_PHASE_CONF(x)			(AD9545_Q0A_PHASE_CONF + ((x) * 0x9))
+#define AD9545_Q1_PHASE_CONF(x)			(AD9545_Q1A_PHASE_CONF + ((x) * 0x9))
+#define AD9545_QX_PHASE_CONF(x) ({						\
+	typeof(x) x_ = (x);							\
+										\
+	(x_ > 5) ? AD9545_Q1_PHASE_CONF(x_ - 6) : AD9545_Q0_PHASE_CONF(x_);	\
+})
+
+#define AD9545_DPLLX_FTW(x)			(AD9545_DPLL0_FTW + ((x) * 0x400))
+#define AD9545_DPLLX_EN(x, y)			(AD9545_DPLL0_EN + ((x) * 0x400) + ((y) * 0x20))
+#define AD9545_DPLLX_SOURCE(x, y)		(AD9545_DPLL0_SOURCE + ((x) * 0x400) + ((y) * 0x20))
+#define AD9545_DPLLX_LOOP_BW(x, y)		(AD9545_DPLL0_LOOP_BW + ((x) * 0x400) + ((y) * 0x20))
+#define AD9545_DPLLX_N_DIV(x, y)		(AD9545_DPLL0_N_DIV + ((x) * 0x400) + ((y) * 0x20))
+#define AD9545_DPLLX_FRAC_DIV(x, y)		(AD9545_DPLL0_FRAC + ((x) * 0x400) + ((y) * 0x20))
+#define AD9545_DPLLX_MOD_DIV(x, y)		(AD9545_DPLL0_MOD + ((x) * 0x400) + ((y) * 0x20))
+#define AD9545_DPLLX_FAST_L1(x, y)		(AD9545_DPLL0_FAST_L1 + ((x) * 0x400) + ((y) * 0x20))
+#define AD9545_DPLLX_FAST_L2(x, y)		(AD9545_DPLL0_FAST_L2 + ((x) * 0x400) + ((y) * 0x20))
+
+#define AD9545_DIV_OPS_Q0(x)			(AD9545_DIV_OPS_Q0A + (x))
+#define AD9545_DIV_OPS_Q1(x)			(AD9545_DIV_OPS_Q1A + (x))
+#define AD9545_DIV_OPS_QX(x) ({						\
+	typeof(x) x_ = (x) / 2;						\
+									\
+	(x_ > 2) ? AD9545_DIV_OPS_Q1(x_ - 3) : AD9545_DIV_OPS_Q0(x_);	\
+})
+
+#define AD9545_PWR_CALIB_CHX(x)			(AD9545_PWR_CALIB_CH0 + ((x) * 0x100))
+#define AD9545_PLLX_STATUS(x)			(AD9545_PLL0_STATUS + ((x) * 0x100))
+#define AD9545_DPLLX_FAST_MODE(x)		(AD9545_DPLL0_FAST_MODE + ((x) * 0x100))
+#define AD9545_REFX_STATUS(x)			(AD9545_REFA_STATUS + (x))
+
+#define AD9545_PROFILE_SEL_MODE_MSK		GENMASK(3, 2)
+#define AD9545_PROFILE_SEL_MODE(x)		FIELD_PREP(AD9545_PROFILE_SEL_MODE_MSK, x)
+
+#define AD9545_NCOX_FREQ(x)			(AD9545_NCO0_FREQ + ((x) * 0x40))
+
+#define AD9545_TDCX_DIV(x)			(AD9545_TDC0_DIV + ((x) * 0x9))
+#define AD9545_TDCX_PERIOD(x)			(AD9545_TDC0_PERIOD + ((x) * 0x9))
+
+/* AD9545 MX PIN bitfields */
+#define AD9545_MX_TO_TDCX(x)			(0x30 + (x))
+
+/* AD9545 COMPENSATE TDCS bitfields */
+#define AD9545_COMPENSATE_TDCS_VIA_AUX_DPLL	0x4
+
+/* AD9545 COMPENSATE DPLL bitfields */
+#define AD9545_COMPNESATE_VIA_AUX_DPLL		0x44
+
+/* define AD9545_DPLLX_EN bitfields */
+#define AD9545_EN_PROFILE_MSK			BIT(0)
+#define AD9545_SEL_PRIORITY_MSK			GENMASK(5, 1)
+
+/* AD9545_PWR_CALIB_CHX bitfields */
+#define AD9545_PWR_DOWN_CH			BIT(0)
+#define AD9545_CALIB_APLL			BIT(1)
+
+/* AD9545_SYNC_CTRLX bitfields */
+#define AD9545_SYNC_CTRL_DPLL_REF_MSK		BIT(2)
+#define AD9545_SYNC_CTRL_MODE_MSK		GENMASK(1, 0)
+
+/* AD9545_QX_PHASE_CONF bitfields */
+#define AD9545_QX_HALF_DIV_MSK			BIT(5)
+#define AD9545_QX_PHASE_32_MSK			BIT(6)
+
+/* AD9545_DIV_OPS_QX bitfields */
+#define AD9545_DIV_OPS_MUTE_A_MSK		BIT(2)
+#define AD9545_DIV_OPS_MUTE_AA_MSK		BIT(3)
+
+/* AD9545_PLL_STATUS bitfields */
+#define AD9545_PLLX_LOCK(x, y)			((1 << (4 + (x))) & (y))
+
+/* AD9545_MISC bitfields */
+#define AD9545_MISC_AUX_NC0_ERR_MSK		GENMASK(5, 4)
+#define AD9545_MISC_AUX_NC1_ERR_MSK		GENMASK(7, 6)
+#define AD9545_AUX_DPLL_LOCK_MSK		BIT(1)
+#define AD9545_AUX_DPLL_REF_FAULT		BIT(2)
+
+/* AD9545_REFX_STATUS bitfields */
+#define AD9545_REFX_VALID_MSK			BIT(4)
+
+#define AD9545_SYS_PLL_STABLE_MSK		GENMASK(1, 0)
+#define AD9545_SYS_PLL_STABLE(x)		(((x) & AD9545_SYS_PLL_STABLE_MSK) == 0x3)
+
+#define AD9545_APLL_LOCKED(x)			((x) & BIT(3))
+
+#define AD9545_SYS_CLK_STABILITY_MS	50
+
+#define AD9545_R_DIV_MAX		0x40000000
+#define AD9545_IN_MAX_TDC_FREQ_HZ	200000
+
+#define AD9545_MAX_REFS			4
+
+#define AD9545_APLL_M_DIV_MIN		14
+#define AD9545_APLL_M_DIV_MAX		255
+
+#define AD9545_DPLL_MAX_N		1073741823
+#define AD9545_DPLL_MAX_FRAC		116777215
+#define AD9545_DPLL_MAX_MOD		116777215
+#define AD9545_MAX_DPLL_PROFILES	6
+
+#define AD9545_NCO_MAX_FREQ		65535
+
+static const unsigned int ad9545_apll_rate_ranges_hz[2][2] = {
+	{2400000000U, 3200000000U}, {3200000000U, 4000000000U}
+};
+
+static const unsigned int ad9545_apll_pfd_rate_ranges_hz[2] = {
+	162000000U, 300000000U
+};
+
+static const unsigned short ad9545_vco_calibration_op[][2] = {
+	{AD9545_CALIB_CLK, 0},
+	{AD9545_IO_UPDATE, AD9545_UPDATE_REGS},
+	{AD9545_CALIB_CLK, BIT(2)},
+	{AD9545_IO_UPDATE, AD9545_UPDATE_REGS},
+};
+
+static const u8 ad9545_tdc_source_mapping[] = {
+	0, 1, 2, 3, 8, 9,
+};
+
+static const u32 ad9545_fast_acq_excess_bw_map[] = {
+	0, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,
+};
+
+static const u32 ad9545_fast_acq_timeout_map[] = {
+	1, 10, 50, 100, 500, 1000, 10000, 50000,
+};
+
+static const u32 ad9545_hyst_scales_bp[] = {
+	0, 3125, 6250, 12500, 25000, 50000, 75000, 87500
+};
+
+static const u32 ad9545_out_source_ua[] = {
+	7500, 12500, 15000
+};
+
+static const u32 ad9545_rate_change_limit_map[] = {
+	715, 1430, 2860, 5720, 11440, 22880, 45760,
+};
+
+static const char * const ad9545_ref_m_clk_names[] = {
+	"Ref-M0", "Ref-M1", "Ref-M2",
+};
+
+static const char * const ad9545_ref_clk_names[] = {
+	"Ref-A", "Ref-AA", "Ref-B", "Ref-BB",
+};
+
+static const char * const ad9545_in_clk_names[] = {
+	"Ref-A-Div", "Ref-AA-Div", "Ref-B-Div", "Ref-BB-Div",
+};
+
+static const char * const ad9545_out_clk_names[] = {
+	"Q0A-div", "Q0AA-div", "Q0B-div", "Q0BB-div", "Q0C-div", "Q0CC-div", "Q1A-div", "Q1AA-div",
+	"Q1B-div", "Q1BB-div",
+};
+
+static const char * const ad9545_pll_clk_names[] = {
+	"PLL0", "PLL1",
+};
+
+static const char * const ad9545_aux_nco_clk_names[] = {
+	"AUX_NCO0", "AUX_NCO1",
+};
+
+static const char * const ad9545_aux_tdc_clk_names[] = {
+	"AUX_TDC0", "AUX_TDC1",
+};
+
+static const char *ad9545_aux_dpll_name = "AUX_DPLL";
+
+enum ad9545_ref_mode {
+	AD9545_SINGLE_ENDED = 0,
+	AD9545_DIFFERENTIAL,
+};
+
+enum ad9545_single_ended_config {
+	AD9545_AC_COUPLED_IF = 0,
+	AD9545_DC_COUPLED_1V2,
+	AD9545_DC_COUPLED_1V8,
+	AD9545_IN_PULL_UP,
+};
+
+enum ad9545_diferential_config {
+	AD9545_AC_COUPLED = 0,
+	AD9545_DC_COUPLED,
+	AD9545_DC_COUPLED_LVDS,
+};
+
+enum ad9545_output_mode {
+	AD9545_SINGLE_DIV_DIF = 0,
+	AD9545_SINGLE_DIV,
+	AD9545_DUAL_DIV,
+};
+
+struct ad9545_out_clk {
+	struct ad9545_state		*st;
+	bool				output_used;
+	bool				source_current;
+	enum ad9545_output_mode		output_mode;
+	u32				source_ua;
+	struct clk_hw			hw;
+	unsigned int			address;
+};
+
+struct ad9545_dpll_profile {
+	unsigned int			address;
+	unsigned int			parent_index;
+	unsigned int			priority;
+	unsigned int			loop_bw_uhz;
+	unsigned int			fast_acq_excess_bw;
+	unsigned int			fast_acq_timeout_ms;
+	unsigned int			fast_acq_settle_ms;
+	bool				en;
+	u8				tdc_source;
+};
+
+struct ad9545_ppl_clk {
+	struct ad9545_state		*st;
+	bool				pll_used;
+	unsigned int			address;
+	struct clk_hw			hw;
+	unsigned int			num_parents;
+	const struct clk_hw		**parents;
+	struct ad9545_dpll_profile	profiles[AD9545_MAX_DPLL_PROFILES];
+	unsigned int			free_run_freq;
+	unsigned int			fast_acq_trigger_mode;
+};
+
+struct ad9545_ref_in_clk {
+	struct clk_hw			hw;
+	struct ad9545_state		*st;
+	u32				r_div_ratio;
+	bool				ref_used;
+	u32				d_tol_ppb;
+	u8				monitor_hyst_scale;
+	u32				valid_t_ms;
+	struct clk			*parent_clk;
+	unsigned int			address;
+	enum ad9545_ref_mode		mode;
+	unsigned int			freq_thresh_ps;
+	unsigned int			phase_thresh_ps;
+	unsigned int			phase_lock_fill_rate;
+	unsigned int			phase_lock_drain_rate;
+	unsigned int			freq_lock_fill_rate;
+	unsigned int			freq_lock_drain_rate;
+	union {
+		enum ad9545_single_ended_config		s_conf;
+		enum ad9545_diferential_config		d_conf;
+	};
+};
+
+struct ad9545_aux_nco_clk {
+	struct clk_hw			hw;
+	bool				nco_used;
+	struct ad9545_state		*st;
+	unsigned int			address;
+	unsigned int			freq_thresh_ps;
+	unsigned int			phase_thresh_ps;
+};
+
+struct ad9545_aux_tdc_clk {
+	struct clk_hw			hw;
+	bool				tdc_used;
+	struct ad9545_state		*st;
+	unsigned int			address;
+	unsigned int			pin_nr;
+};
+
+struct ad9545_aux_dpll_clk {
+	struct clk_hw			hw;
+	bool				dpll_used;
+	struct ad9545_state		*st;
+	unsigned int			source;
+	unsigned int			loop_bw_mhz;
+	unsigned int			rate_change_limit;
+};
+
+struct ad9545_sys_clk {
+	bool				sys_clk_freq_doubler;
+	bool				sys_clk_crystal;
+	u32				ref_freq_hz;
+	u32				sys_freq_hz;
+};
+
+struct ad9545_state {
+	struct device			*dev;
+	struct regmap			*regmap;
+	struct ad9545_sys_clk		sys_clk;
+	struct ad9545_aux_dpll_clk	aux_dpll_clk;
+	struct ad9545_ppl_clk		pll_clks[ARRAY_SIZE(ad9545_pll_clk_names)];
+	struct ad9545_ref_in_clk	ref_in_clks[ARRAY_SIZE(ad9545_ref_clk_names)];
+	struct ad9545_out_clk		out_clks[ARRAY_SIZE(ad9545_out_clk_names)];
+	struct ad9545_aux_nco_clk	aux_nco_clks[ARRAY_SIZE(ad9545_aux_nco_clk_names)];
+	struct ad9545_aux_tdc_clk	aux_tdc_clks[ARRAY_SIZE(ad9545_aux_tdc_clk_names)];
+	struct clk			**clks[4];
+};
+
+#define to_ref_in_clk(_hw)	container_of(_hw, struct ad9545_ref_in_clk, hw)
+#define to_pll_clk(_hw)		container_of(_hw, struct ad9545_ppl_clk, hw)
+#define to_out_clk(_hw)		container_of(_hw, struct ad9545_out_clk, hw)
+#define to_nco_clk(_hw)		container_of(_hw, struct ad9545_aux_nco_clk, hw)
+#define to_tdc_clk(_hw)		container_of(_hw, struct ad9545_aux_tdc_clk, hw)
+
+static int ad9545_parse_dt_inputs(struct ad9545_state *st)
+{
+	struct fwnode_handle *inputs_node;
+	struct fwnode_handle *fwnode;
+	struct fwnode_handle *child;
+	struct clk *clk;
+	bool prop_found;
+	int ref_ind;
+	u32 val;
+	int ret;
+	int i;
+
+	fwnode = dev_fwnode(st->dev);
+	inputs_node = fwnode_get_named_child_node(fwnode, "ref-input-clks");
+	if (!inputs_node)
+		return 0;
+
+	prop_found = false;
+	fwnode_for_each_available_child_node(inputs_node, child) {
+		ret = fwnode_property_read_u32(child, "reg", &ref_ind);
+		if (ret < 0) {
+			dev_err(st->dev, "reg not specified in ref node.");
+			return ret;
+		}
+
+		if (ref_ind > 3)
+			return -EINVAL;
+
+		st->ref_in_clks[ref_ind].ref_used = true;
+		st->ref_in_clks[ref_ind].address = ref_ind;
+		st->ref_in_clks[ref_ind].st = st;
+
+		prop_found = fwnode_property_present(child, "adi,single-ended-mode");
+		if (prop_found) {
+			st->ref_in_clks[ref_ind].mode = AD9545_SINGLE_ENDED;
+			ret = fwnode_property_read_u32(child, "adi,single-ended-mode", &val);
+			if (ret < 0)
+				return ret;
+
+			st->ref_in_clks[ref_ind].s_conf = val;
+		} else {
+			st->ref_in_clks[ref_ind].mode = AD9545_DIFFERENTIAL;
+			ret = fwnode_property_read_u32(child, "adi,differential-mode", &val);
+			if (ret < 0)
+				return ret;
+
+			st->ref_in_clks[ref_ind].d_conf = val;
+		}
+
+		ret = fwnode_property_read_u32(child, "adi,r-divider-ratio", &val);
+		if (ret < 0) {
+			dev_err(st->dev, "No r-divider-ratio specified for ref: %d", ref_ind);
+			return ret;
+		}
+
+		st->ref_in_clks[ref_ind].r_div_ratio = val;
+
+		ret = fwnode_property_read_u32(child, "adi,ref-dtol-pbb", &val);
+		if (ret < 0) {
+			dev_err(st->dev, "No ref-dtol-pbb specified for ref: %d", ref_ind);
+			return ret;
+		}
+
+		st->ref_in_clks[ref_ind].d_tol_ppb = val;
+
+		ret = fwnode_property_read_u32(child, "adi,ref-monitor-hysteresis-pbb", &val);
+		if (ret < 0) {
+			dev_err(st->dev, "No ref-monitor-hysteresis-pbb specified for ref: %d",
+				ref_ind);
+			return ret;
+		}
+
+		for (i = 0; i < ARRAY_SIZE(ad9545_hyst_scales_bp); i++) {
+			if (ad9545_hyst_scales_bp[i] == val) {
+				st->ref_in_clks[ref_ind].monitor_hyst_scale = i;
+				break;
+			}
+		}
+
+		if (i == ARRAY_SIZE(ad9545_hyst_scales_bp))
+			return -EINVAL;
+
+		ret = fwnode_property_read_u32(child, "adi,ref-validation-timer-ms", &val);
+		if (ret < 0) {
+			dev_err(st->dev, "No ref-validation-timer-ms specified for ref: %d",
+				ref_ind);
+			return ret;
+		}
+
+		st->ref_in_clks[ref_ind].valid_t_ms = val;
+
+		ret = fwnode_property_read_u32(child, "adi,freq-lock-threshold-ps", &val);
+		if (ret < 0) {
+			dev_err(st->dev, "No freq-lock-threshold-ps specified for ref: %d",
+				ref_ind);
+			return ret;
+		}
+
+		st->ref_in_clks[ref_ind].freq_thresh_ps = val;
+
+		ret = fwnode_property_read_u32(child, "adi,phase-lock-threshold-ps", &val);
+		if (ret < 0) {
+			dev_err(st->dev, "No phase-lock-threshold-ps specified for ref: %d",
+				ref_ind);
+			return ret;
+		}
+
+		st->ref_in_clks[ref_ind].phase_thresh_ps = val;
+
+		ret = fwnode_property_read_u32(child, "adi,phase-lock-fill-rate", &val);
+		if (!ret)
+			st->ref_in_clks[ref_ind].phase_lock_fill_rate = val;
+
+		ret = fwnode_property_read_u32(child, "adi,phase-lock-drain-rate", &val);
+		if (!ret)
+			st->ref_in_clks[ref_ind].phase_lock_drain_rate = val;
+
+		ret = fwnode_property_read_u32(child, "adi,freq-lock-fill-rate", &val);
+		if (!ret)
+			st->ref_in_clks[ref_ind].freq_lock_fill_rate = val;
+
+		ret = fwnode_property_read_u32(child, "adi,freq-lock-drain-rate", &val);
+		if (!ret)
+			st->ref_in_clks[ref_ind].freq_lock_drain_rate = val;
+
+		clk = devm_clk_get(st->dev, ad9545_ref_clk_names[ref_ind]);
+		if (IS_ERR(clk))
+			return PTR_ERR(clk);
+
+		st->ref_in_clks[ref_ind].parent_clk = clk;
+	}
+
+	return 0;
+}
+
+static int ad9545_parse_dt_plls(struct ad9545_state *st)
+{
+	struct fwnode_handle *profile_node;
+	struct fwnode_handle *pll_clks;
+	struct fwnode_handle *fwnode;
+	struct fwnode_handle *child;
+	u32 profile_addr;
+	u32 val;
+	u32 addr;
+	int ret;
+
+	fwnode = dev_fwnode(st->dev);
+	pll_clks = fwnode_get_named_child_node(fwnode, "pll-clks");
+	if (!pll_clks)
+		return 0;
+
+	fwnode_for_each_available_child_node(pll_clks, child) {
+		ret = fwnode_property_read_u32(child, "reg", &addr);
+		if (ret < 0)
+			return ret;
+
+		if (addr > 1)
+			return -EINVAL;
+
+		st->pll_clks[addr].pll_used = true;
+		st->pll_clks[addr].address = addr;
+
+		ret = fwnode_property_read_u32(profile_node, "adi,fast-acq-trigger-mode", &val);
+		if (!ret)
+			st->pll_clks[addr].fast_acq_trigger_mode = val;
+
+		/* parse DPLL profiles */
+		fwnode_for_each_available_child_node(child, profile_node) {
+			ret = fwnode_property_read_u32(profile_node, "reg", &profile_addr);
+			if (ret < 0) {
+				dev_err(st->dev, "Could not read Profile reg property.");
+				return ret;
+			}
+
+			if (profile_addr >= AD9545_MAX_DPLL_PROFILES)
+				return -EINVAL;
+
+			st->pll_clks[addr].profiles[profile_addr].en = true;
+			st->pll_clks[addr].profiles[profile_addr].address = profile_addr;
+
+			ret = fwnode_property_read_u32(profile_node, "adi,pll-loop-bandwidth-uhz", &val);
+			if (ret < 0) {
+				dev_err(st->dev, "Could not read Profile %d, pll-loop-bandwidth.",
+					profile_addr);
+				return ret;
+			}
+
+			st->pll_clks[addr].profiles[profile_addr].loop_bw_uhz = val;
+
+			ret = fwnode_property_read_u32(profile_node, "adi,fast-acq-excess-bw",
+						       &val);
+			if (!ret)
+				st->pll_clks[addr].profiles[profile_addr].fast_acq_excess_bw = val;
+
+			ret = fwnode_property_read_u32(profile_node, "adi,fast-acq-timeout-ms",
+						       &val);
+			if (!ret)
+				st->pll_clks[addr].profiles[profile_addr].fast_acq_timeout_ms = val;
+
+			ret = fwnode_property_read_u32(profile_node, "adi,fast-acq-lock-settle-ms",
+						       &val);
+			if (!ret)
+				st->pll_clks[addr].profiles[profile_addr].fast_acq_settle_ms = val;
+
+			ret = fwnode_property_read_u32(profile_node, "adi,profile-priority", &val);
+			if (!ret)
+				st->pll_clks[addr].profiles[profile_addr].priority = val;
+
+			ret = fwnode_property_read_u32(profile_node, "adi,pll-source", &val);
+			if (ret < 0) {
+				dev_err(st->dev, "Could not read Profile %d, pll-loop-bandwidth.",
+					profile_addr);
+				return ret;
+			}
+
+			if (val > 5)
+				return -EINVAL;
+
+			st->pll_clks[addr].profiles[profile_addr].tdc_source = val;
+		}
+	}
+
+	return 0;
+}
+
+static int ad9545_parse_dt_outputs(struct ad9545_state *st)
+{
+	struct fwnode_handle *output_clks;
+	struct fwnode_handle *fwnode;
+	struct fwnode_handle *child;
+	int out_ind;
+	u32 val;
+	int ret;
+
+	fwnode = dev_fwnode(st->dev);
+	output_clks = fwnode_get_named_child_node(fwnode, "output-clks");
+	if (!output_clks)
+		return 0;
+
+	fwnode_for_each_available_child_node(output_clks, child) {
+		ret = fwnode_property_read_u32(child, "reg", &out_ind);
+		if (ret < 0) {
+			dev_err(st->dev, "No reg specified for output.");
+			return ret;
+		}
+
+		if (out_ind > 9)
+			return -EINVAL;
+
+		st->out_clks[out_ind].output_used = true;
+		st->out_clks[out_ind].address = out_ind;
+
+		if (fwnode_property_present(child, "adi,current-source"))
+			st->out_clks[out_ind].source_current = true;
+
+		ret = fwnode_property_read_u32(child, "adi,current-source-microamp", &val);
+		if (ret < 0) {
+			dev_err(st->dev, "No current-source-microamp specified for output: %d",
+				out_ind);
+			return ret;
+		}
+
+		st->out_clks[out_ind].source_ua = val;
+
+		ret = fwnode_property_read_u32(child, "adi,output-mode", &val);
+		if (ret < 0) {
+			dev_err(st->dev, "No output-mode specified for output: %d", out_ind);
+			return ret;
+		}
+
+		st->out_clks[out_ind].output_mode = val;
+	}
+
+	return 0;
+}
+
+static int ad9545_parse_dt_ncos(struct ad9545_state *st)
+{
+	struct fwnode_handle *aux_ncos;
+	struct fwnode_handle *fwnode;
+	struct fwnode_handle *child;
+	u32 val;
+	u32 addr;
+	int ret;
+
+	fwnode = dev_fwnode(st->dev);
+	aux_ncos = fwnode_get_named_child_node(fwnode, "aux-ncos");
+	if (!aux_ncos)
+		return 0;
+
+	fwnode_for_each_available_child_node(aux_ncos, child) {
+		ret = fwnode_property_read_u32(child, "reg", &addr);
+		if (ret < 0) {
+			dev_err(st->dev, "No reg specified for aux. NCO.");
+			return ret;
+		}
+
+		if (addr > 1)
+			return -EINVAL;
+
+		st->aux_nco_clks[addr].nco_used = true;
+		st->aux_nco_clks[addr].address = addr;
+		st->aux_nco_clks[addr].st = st;
+
+		ret = fwnode_property_read_u32(child, "adi,freq-lock-threshold-ps", &val);
+		if (ret < 0) {
+			dev_err(st->dev, "No freq-lock-threshold-ps specified for aux. NCO: %d",
+				addr);
+			return ret;
+		}
+
+		st->aux_nco_clks[addr].freq_thresh_ps = val;
+
+		ret = fwnode_property_read_u32(child, "adi,phase-lock-threshold-ps", &val);
+		if (ret < 0) {
+			dev_err(st->dev, "No phase-lock-threshold-ps specified for aux. NCO: %d",
+				addr);
+			return ret;
+		}
+
+		st->aux_nco_clks[addr].phase_thresh_ps = val;
+	}
+
+	return 0;
+}
+
+static int ad9545_parse_dt_tdcs(struct ad9545_state *st)
+{
+	struct fwnode_handle *aux_tdc_clks;
+	struct fwnode_handle *fwnode;
+	struct fwnode_handle *child;
+	u32 val;
+	u32 addr;
+	int ret;
+
+	fwnode = dev_fwnode(st->dev);
+	aux_tdc_clks = fwnode_get_named_child_node(fwnode, "aux-tdc-clks");
+	if (!aux_tdc_clks)
+		return 0;
+
+	fwnode_for_each_available_child_node(aux_tdc_clks, child) {
+		ret = fwnode_property_read_u32(child, "reg", &addr);
+		if (ret < 0) {
+			dev_err(st->dev, "No reg specified for aux. TDC.");
+			return ret;
+		}
+
+		if (addr > 1) {
+			dev_err(st->dev, "Invalid address: %u for aux. TDC.", addr);
+			return -EINVAL;
+		}
+
+		st->aux_tdc_clks[addr].tdc_used = true;
+		st->aux_tdc_clks[addr].address = addr;
+		st->aux_tdc_clks[addr].st = st;
+
+		ret = fwnode_property_read_u32(child, "adi,pin-nr", &val);
+		if (ret < 0) {
+			dev_err(st->dev, "No source pin specified for aux. TDC: %d", addr);
+			return ret;
+		}
+
+		if (val >= ARRAY_SIZE(ad9545_ref_m_clk_names)) {
+			dev_err(st->dev, "Invalid Mx pin-nr: %d", val);
+			return -EINVAL;
+		}
+
+		st->aux_tdc_clks[addr].pin_nr = val;
+	}
+
+	return 0;
+}
+
+static int ad9545_parse_dt_aux_dpll(struct ad9545_state *st)
+{
+	struct fwnode_handle *fwnode;
+	struct fwnode_handle *child;
+	u32 val;
+	int ret;
+
+	fwnode = dev_fwnode(st->dev);
+	child = fwnode_get_named_child_node(fwnode, "aux-dpll");
+	if (!child)
+		return 0;
+
+	st->aux_dpll_clk.dpll_used = true;
+	st->aux_dpll_clk.st = st;
+
+	ret = fwnode_property_read_u32(child, "adi,compensation-source", &val);
+	if (ret < 0) {
+		dev_err(st->dev, "No TDC source specified for aux. DPLL.");
+		return ret;
+	}
+
+	st->aux_dpll_clk.source = val;
+
+	ret = fwnode_property_read_u32(child, "adi,aux-dpll-bw-mhz", &val);
+	if (ret < 0) {
+		dev_err(st->dev, "No loop bw specified for aux. DPLL.");
+		return ret;
+	}
+
+	st->aux_dpll_clk.loop_bw_mhz = val;
+
+	ret = fwnode_property_read_u32(child, "adi,rate-change-limit", &val);
+	if (!ret)
+		st->aux_dpll_clk.rate_change_limit = val;
+
+	return 0;
+}
+
+static int ad9545_parse_dt(struct ad9545_state *st)
+{
+	struct fwnode_handle *fwnode;
+	int ret;
+
+	fwnode = dev_fwnode(st->dev);
+
+	ret = fwnode_property_read_u32(fwnode, "adi,ref-frequency-hz", &st->sys_clk.ref_freq_hz);
+	if (ret < 0) {
+		dev_err(st->dev, "No ref-frequency-hz specified.");
+		return ret;
+	}
+
+	st->sys_clk.sys_clk_crystal = fwnode_property_present(fwnode, "adi,ref-crystal");
+	st->sys_clk.sys_clk_freq_doubler = fwnode_property_present(fwnode, "adi,freq-doubler");
+
+	ret = ad9545_parse_dt_inputs(st);
+	if (ret < 0)
+		return ret;
+
+	ret = ad9545_parse_dt_plls(st);
+	if (ret < 0)
+		return ret;
+
+	ret = ad9545_parse_dt_outputs(st);
+	if (ret < 0)
+		return ret;
+
+	ret = ad9545_parse_dt_ncos(st);
+	if (ret < 0)
+		return ret;
+
+	ret = ad9545_parse_dt_tdcs(st);
+	if (ret < 0)
+		return ret;
+
+	ret = ad9545_parse_dt_aux_dpll(st);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int ad9545_check_id(struct ad9545_state *st)
+{
+	u32 chip_id;
+	u32 val;
+	int ret;
+
+	ret = regmap_read(st->regmap, AD9545_PRODUCT_ID_LOW, &val);
+	if (ret < 0)
+		return ret;
+
+	chip_id = val;
+	ret = regmap_read(st->regmap, AD9545_PRODUCT_ID_HIGH, &val);
+	if (ret < 0)
+		return ret;
+
+	chip_id += val << 8;
+	if (chip_id != AD9545_CHIP_ID) {
+		dev_err(st->dev, "Unrecognized CHIP_ID 0x%X\n", chip_id);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int ad9545_io_update(struct ad9545_state *st)
+{
+	return regmap_write(st->regmap, AD9545_IO_UPDATE, AD9545_UPDATE_REGS);
+}
+
+static int ad9545_sys_clk_setup(struct ad9545_state *st)
+{
+	u64 ref_freq_milihz;
+	__le64 regval64;
+	u8 div_ratio;
+	u32 fosc;
+	int ret;
+	u8 val;
+	u32 fs;
+	int i;
+
+	/*
+	 * System frequency must be between 2250 MHz and 2415 MHz.
+	 * fs = fosc * K / j
+	 * K - feedback divider ratio [4, 255]
+	 * j = 1/2 if frequency doubler is enabled
+	 */
+	fosc = DIV_ROUND_UP(st->sys_clk.ref_freq_hz, 1000000);
+
+	if (st->sys_clk.sys_clk_freq_doubler)
+		fosc *= 2;
+
+	div_ratio = 0;
+	for (i = 4; i < 256; i++) {
+		fs = i * fosc;
+
+		if (fs > 2250 && fs < 2415) {
+			div_ratio = i;
+			break;
+		}
+	}
+
+	if (!div_ratio) {
+		dev_err(st->dev, "No feedback divider ratio for sys clk PLL found.\n");
+		return -EINVAL;
+	}
+
+	st->sys_clk.sys_freq_hz = st->sys_clk.ref_freq_hz * div_ratio;
+	if (st->sys_clk.sys_clk_freq_doubler)
+		st->sys_clk.sys_freq_hz *= 2;
+
+	ret = regmap_write(st->regmap, AD9545_SYS_CLK_FB_DIV, div_ratio);
+	if (ret < 0)
+		return ret;
+
+	/* enable crystal maintaining amplifier */
+	val = 0;
+	if (st->sys_clk.sys_clk_crystal)
+		val |= BIT(3);
+
+	if (st->sys_clk.sys_clk_freq_doubler)
+		val |= BIT(0);
+
+	ret = regmap_write(st->regmap, AD9545_SYS_CLK_INPUT, val);
+	if (ret < 0)
+		return ret;
+
+	/* write reference frequency provided at XOA, XOB in milliherz */
+	ref_freq_milihz = mul_u32_u32(st->sys_clk.ref_freq_hz, 1000);
+	regval64 = cpu_to_le64(ref_freq_milihz);
+
+	ret = regmap_bulk_write(st->regmap, AD9545_SYS_CLK_REF_FREQ, &regval64, 5);
+	if (ret < 0)
+		return ret;
+
+	return regmap_write(st->regmap, AD9545_SYS_STABILITY_T, AD9545_SYS_CLK_STABILITY_MS);
+}
+
+static int ad9545_get_q_div(struct ad9545_state *st, int addr, u32 *q_div)
+{
+	__le32 regval;
+	int ret;
+
+	ret = regmap_bulk_read(st->regmap, AD9545_QX_DIV(addr), &regval, 4);
+	if (ret < 0)
+		return ret;
+
+	*q_div = le32_to_cpu(regval);
+
+	return 0;
+}
+
+static int ad9545_set_q_div(struct ad9545_state *st, int addr, u32 q_div)
+{
+	__le32 regval;
+	int ret;
+
+	regval = cpu_to_le32(q_div);
+	ret = regmap_bulk_write(st->regmap, AD9545_QX_DIV(addr), &regval, 4);
+	if (ret < 0)
+		return ret;
+
+	return ad9545_io_update(st);
+}
+
+static unsigned long ad95452_out_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+	struct ad9545_out_clk *clk = to_out_clk(hw);
+	u32 qdiv;
+	int ret;
+
+	ret = ad9545_get_q_div(clk->st, clk->address, &qdiv);
+	if (ret < 0) {
+		dev_err(clk->st->dev, "Could not read Q div value.");
+		return 0;
+	}
+
+	return div_u64(parent_rate, qdiv);
+}
+
+static long ad9545_out_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+				      unsigned long *parent_rate)
+{
+	u32 out_rate;
+	u32 qdiv;
+
+	qdiv = div64_u64(*parent_rate, rate);
+	if (!qdiv)
+		out_rate = *parent_rate;
+	else
+		out_rate = div_u64(*parent_rate, qdiv);
+
+	return out_rate;
+}
+
+static int ad9545_out_clk_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate)
+{
+	struct ad9545_out_clk *clk = to_out_clk(hw);
+	u32 qdiv = div64_u64(parent_rate, rate);
+
+	if (!qdiv)
+		qdiv = 1;
+
+	return ad9545_set_q_div(clk->st, clk->address, qdiv);
+}
+
+static int ad9545_out_clk_set_phase(struct clk_hw *hw, int degrees)
+{
+	struct ad9545_out_clk *clk = to_out_clk(hw);
+	u64 phase_code;
+	u32 phase_conf;
+	__le64 regval;
+	u32 half_div;
+	u32 qdiv;
+	int ret;
+
+	ret = ad9545_get_q_div(clk->st, clk->address, &qdiv);
+	if (ret < 0)
+		return ret;
+
+	ret = regmap_read(clk->st->regmap, AD9545_QX_PHASE_CONF(clk->address), &phase_conf);
+	if (ret < 0)
+		return ret;
+
+	half_div = !!(phase_conf & AD9545_QX_HALF_DIV_MSK);
+
+	/* Qxy phase bitfield depends on the current Q div value */
+	phase_code = qdiv;
+	phase_code = div_u64((phase_code * 2 + half_div) * degrees, 360);
+
+	/* Qxy phase bitfield is 33 bits long, with last bit in PHASE_CONF reg */
+	regval = cpu_to_le64(phase_code & 0xFFFFFFFF);
+	ret = regmap_bulk_write(clk->st->regmap, AD9545_QX_PHASE(clk->address), &regval, 4);
+	if (ret < 0)
+		return ret;
+
+	if (phase_code > U32_MAX) {
+		ret = regmap_update_bits(clk->st->regmap, AD9545_QX_PHASE_CONF(clk->address),
+					 AD9545_QX_PHASE_32_MSK, AD9545_QX_PHASE_32_MSK);
+		if (ret < 0)
+			return ret;
+	}
+
+	return ad9545_io_update(clk->st);
+}
+
+static int ad9545_out_clk_get_phase(struct clk_hw *hw)
+{
+	struct ad9545_out_clk *clk = to_out_clk(hw);
+	u64 input_edges_nr;
+	u64 phase_code;
+	__le32 regval;
+	u32 phase_conf;
+	u32 qdiv;
+	int ret;
+
+	ret = ad9545_get_q_div(clk->st, clk->address, &qdiv);
+	if (ret < 0)
+		return ret;
+
+	ret = regmap_read(clk->st->regmap, AD9545_QX_PHASE_CONF(clk->address), &phase_conf);
+	if (ret < 0)
+		return ret;
+
+	ret = regmap_bulk_read(clk->st->regmap, AD9545_QX_PHASE(clk->address), &regval, 4);
+	if (ret < 0)
+		return ret;
+
+	/* Qxy phase bitfield is 33 bits long, with last bit in PHASE_CONF reg */
+	phase_code = !!(phase_conf & AD9545_QX_PHASE_32_MSK);
+	phase_code = (phase_code >> 32) + cpu_to_le32(regval);
+
+	input_edges_nr = 2 * qdiv + !!(phase_conf & AD9545_QX_HALF_DIV_MSK);
+
+	/*
+	 * phase = 360 * (Qxy Phase / E) where:
+	 * E is the total number of input edges per output period of the Q-divider.
+	 */
+	return div64_u64(phase_code * 360, input_edges_nr);
+}
+
+static int ad9545_output_muting(struct ad9545_out_clk *clk, bool mute)
+{
+	u8 regval = 0;
+	int ret;
+	u8 mask;
+
+	if (clk->address % 2)
+		mask = AD9545_DIV_OPS_MUTE_AA_MSK;
+	else
+		mask = AD9545_DIV_OPS_MUTE_A_MSK;
+
+	if (mute)
+		regval = mask;
+
+	ret = regmap_update_bits(clk->st->regmap, AD9545_DIV_OPS_QX(clk->address), mask, regval);
+	if (ret < 0)
+		return ret;
+
+	return ad9545_io_update(clk->st);
+}
+
+static int ad9545_out_clk_enable(struct clk_hw *hw)
+{
+	struct ad9545_out_clk *clk = to_out_clk(hw);
+
+	return ad9545_output_muting(clk, false);
+}
+
+static void ad9545_out_clk_disable(struct clk_hw *hw)
+{
+	struct ad9545_out_clk *clk = to_out_clk(hw);
+
+	ad9545_output_muting(clk, true);
+}
+
+static int ad9545_out_clk_is_enabled(struct clk_hw *hw)
+{
+	struct ad9545_out_clk *clk = to_out_clk(hw);
+	u32 regval;
+	int ret;
+	u8 mask;
+
+	if (clk->address % 2)
+		mask = AD9545_DIV_OPS_MUTE_AA_MSK;
+	else
+		mask = AD9545_DIV_OPS_MUTE_A_MSK;
+
+	ret = regmap_read(clk->st->regmap, AD9545_DIV_OPS_QX(clk->address), &regval);
+	if (ret < 0)
+		return ret;
+
+	return !!(mask & regval);
+}
+
+static const struct clk_ops ad9545_out_clk_ops = {
+	.enable = ad9545_out_clk_enable,
+	.disable = ad9545_out_clk_disable,
+	.is_enabled = ad9545_out_clk_is_enabled,
+	.recalc_rate = ad95452_out_clk_recalc_rate,
+	.round_rate = ad9545_out_clk_round_rate,
+	.set_rate = ad9545_out_clk_set_rate,
+	.set_phase = ad9545_out_clk_set_phase,
+	.get_phase = ad9545_out_clk_get_phase,
+};
+
+static int ad9545_outputs_setup(struct ad9545_state *st)
+{
+	struct clk_init_data init[ARRAY_SIZE(ad9545_out_clk_names)] = {0};
+	int out_i;
+	u16 addr;
+	int ret;
+	u8 reg;
+	int i;
+	int j;
+
+	/* configure current sources */
+	for (i = 0; i < ARRAY_SIZE(ad9545_out_clk_names) / 2; i++) {
+		st->out_clks[i * 2].st = st;
+		st->out_clks[i * 2 + 1].st = st;
+
+		if (st->out_clks[i * 2].output_used)
+			out_i = i * 2;
+		else if (st->out_clks[i * 2 + 1].output_used)
+			out_i = i * 2 + 1;
+		else
+			continue;
+
+		reg = 0;
+		if (st->out_clks[out_i].source_current)
+			reg = 1;
+
+		for (j = 0; j < ARRAY_SIZE(ad9545_out_source_ua); j++)
+			if (ad9545_out_source_ua[j] == st->out_clks[out_i].source_ua)
+				reg |= FIELD_PREP(GENMASK(2, 1), i);
+
+		reg |= FIELD_PREP(GENMASK(4, 3), st->out_clks[out_i].output_mode);
+
+		if (i < 3)
+			addr = AD9545_DRIVER_0A_CONF + i;
+		else
+			addr = AD9545_DRIVER_1A_CONF + (i - 3);
+
+		ret = regmap_write(st->regmap, addr, reg);
+		if (ret < 0)
+			return ret;
+	}
+
+	st->clks[AD9545_CLK_OUT] = devm_kzalloc(st->dev, ARRAY_SIZE(ad9545_out_clk_names) *
+						sizeof(struct clk *), GFP_KERNEL);
+	if (!st->clks[AD9545_CLK_OUT])
+		return -ENOMEM;
+
+	for (i = 0; i < ARRAY_SIZE(ad9545_out_clk_names); i++) {
+		if (!st->out_clks[i].output_used)
+			continue;
+
+		init[i].name = ad9545_out_clk_names[i];
+		init[i].ops = &ad9545_out_clk_ops;
+
+		if (i > 5)
+			init[i].parent_names = &ad9545_pll_clk_names[1];
+		else
+			init[i].parent_names = &ad9545_pll_clk_names[0];
+
+		init[i].num_parents = 1;
+
+		st->out_clks[i].hw.init = &init[i];
+		ret = devm_clk_hw_register(st->dev, &st->out_clks[i].hw);
+		if (ret < 0)
+			return ret;
+
+		st->clks[AD9545_CLK_OUT][i] = st->out_clks[i].hw.clk;
+	}
+
+	/* set to autosync to trigger on DPLL freq lock */
+	for (i = 0; i < ARRAY_SIZE(st->pll_clks); i++) {
+		reg = FIELD_PREP(AD9545_SYNC_CTRL_MODE_MSK, 3);
+		ret = regmap_write(st->regmap, AD9545_SYNC_CTRLX(i), reg);
+		if (ret < 0)
+			return ret;
+	}
+
+	return ad9545_io_update(st);
+}
+
+static int ad9545_set_r_div(struct ad9545_state *st, u32 div, int addr)
+{
+	int ret;
+	u8 reg;
+	int i;
+
+	if (div > AD9545_R_DIV_MAX)
+		return -EINVAL;
+
+	/* r-div ratios are mapped from 0 onward */
+	div -= 1;
+	for (i = 0; i < 4; i++) {
+		reg = (div >> (i * 8)) & 0xFF;
+
+		ret = regmap_write(st->regmap, AD9545_REF_X_RDIV(addr) + i, reg);
+		if (ret < 0)
+			return ret;
+	}
+
+	return ad9545_io_update(st);
+}
+
+static int ad9545_get_r_div(struct ad9545_state *st, int addr, u32 *r_div)
+{
+	int ret;
+	u32 div;
+	u32 reg;
+	int i;
+
+	div = 0;
+	for (i = 0; i < 4; i++) {
+		ret = regmap_read(st->regmap, AD9545_REF_X_RDIV(addr) + i, &reg);
+		if (ret < 0)
+			return ret;
+
+		div += (reg << (i * 8));
+	}
+
+	/* r-div ratios are mapped from 0 onward */
+	*r_div = ++div;
+
+	return 0;
+}
+
+static unsigned long ad95452_in_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+	struct ad9545_ref_in_clk *clk = to_ref_in_clk(hw);
+	u32 div;
+	int ret;
+
+	ret = ad9545_get_r_div(clk->st, clk->address, &div);
+	if (ret < 0) {
+		dev_err(clk->st->dev, "Could not read r div value.");
+		return 1;
+	}
+
+	return DIV_ROUND_CLOSEST(parent_rate, div);
+}
+
+static const struct clk_ops ad9545_in_clk_ops = {
+	.recalc_rate = ad95452_in_clk_recalc_rate,
+};
+
+static int ad9545_input_refs_setup(struct ad9545_state *st)
+{
+	struct clk_init_data init[4] = {0};
+	__le32 regval;
+	__le64 regval64;
+	u64 period_es;
+	int ret;
+	u32 val;
+	u8 reg;
+	int i;
+
+	/* configure input references */
+	for (i = 0; i < ARRAY_SIZE(st->ref_in_clks); i += 2) {
+		if (st->ref_in_clks[i].mode == AD9545_DIFFERENTIAL) {
+			reg = BIT(0);
+			reg |= FIELD_PREP(AD9545_REF_CTRL_DIF_MSK, st->ref_in_clks[i].d_conf);
+		} else {
+			reg = 0;
+			reg |= FIELD_PREP(AD9545_REF_CTRL_REFA_MSK, st->ref_in_clks[i].s_conf);
+			reg |= FIELD_PREP(AD9545_REF_CTRL_REFAA_MSK, st->ref_in_clks[i + 1].s_conf);
+		}
+
+		ret = regmap_write(st->regmap, AD9545_REF_A_CTRL + i * 2, reg);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* configure refs r dividers */
+	for (i = 0; i < ARRAY_SIZE(st->ref_in_clks); i++) {
+		ret = ad9545_set_r_div(st, st->ref_in_clks[i].r_div_ratio, i);
+		if (ret < 0)
+			return ret;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(st->ref_in_clks); i++) {
+		if (!st->ref_in_clks[i].ref_used)
+			continue;
+
+		/* write nominal period in attoseconds */
+		period_es = 1000000000000000000ULL;
+		val = clk_get_rate(st->ref_in_clks[i].parent_clk);
+		if (!val)
+			return -EINVAL;
+
+		period_es = div_u64(period_es, val);
+
+		regval = cpu_to_le32(st->ref_in_clks[i].d_tol_ppb);
+		ret = regmap_bulk_write(st->regmap, AD9545_REF_X_OFFSET_LIMIT(i),
+					&regval, 3);
+		if (ret < 0)
+			return ret;
+
+		regval64 = cpu_to_le64(period_es);
+		ret = regmap_bulk_write(st->regmap, AD9545_REF_X_PERIOD(i), &regval64, 8);
+		if (ret < 0)
+			return ret;
+
+		ret = regmap_write(st->regmap, AD9545_REF_X_MONITOR_HYST(i),
+				   st->ref_in_clks[i].monitor_hyst_scale);
+		if (ret < 0)
+			return ret;
+
+		regval = cpu_to_le32(st->ref_in_clks[i].freq_thresh_ps);
+		ret = regmap_bulk_write(st->regmap, AD9545_SOURCEX_FREQ_THRESH(i),
+					&regval, 3);
+		if (ret < 0)
+			return ret;
+
+		regval = cpu_to_le32(st->ref_in_clks[i].phase_thresh_ps);
+		ret = regmap_bulk_write(st->regmap, AD9545_SOURCEX_PHASE_THRESH(i),
+					&regval, 3);
+		if (ret < 0)
+			return ret;
+
+		regval = st->ref_in_clks[i].freq_lock_fill_rate;
+		if (regval) {
+			ret = regmap_write(st->regmap, AD9545_REF_X_FREQ_LOCK_FILL(i), regval);
+			if (ret < 0)
+				return ret;
+		}
+
+		regval = st->ref_in_clks[i].freq_lock_drain_rate;
+		if (regval) {
+			ret = regmap_write(st->regmap, AD9545_REF_X_FREQ_LOCK_DRAIN(i), regval);
+			if (ret < 0)
+				return ret;
+		}
+
+		regval = st->ref_in_clks[i].phase_lock_fill_rate;
+		if (regval) {
+			ret = regmap_write(st->regmap, AD9545_REF_X_PHASE_LOCK_FILL(i), regval);
+			if (ret < 0)
+				return ret;
+		}
+
+		regval = st->ref_in_clks[i].phase_lock_drain_rate;
+		if (regval) {
+			ret = regmap_write(st->regmap, AD9545_REF_X_PHASE_LOCK_DRAIN(i), regval);
+			if (ret < 0)
+				return ret;
+		}
+
+		init[i].name = ad9545_in_clk_names[i];
+		init[i].ops = &ad9545_in_clk_ops;
+		init[i].parent_names = &ad9545_ref_clk_names[i];
+		init[i].num_parents = 1;
+
+		st->ref_in_clks[i].hw.init = &init[i];
+		ret = devm_clk_hw_register(st->dev, &st->ref_in_clks[i].hw);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* disable unused references */
+	reg = 0;
+	for (i = 0; i < ARRAY_SIZE(st->ref_in_clks); i++) {
+		if (!st->ref_in_clks[i].ref_used)
+			reg |= (1 << i);
+	}
+
+	return regmap_write(st->regmap, AD9545_POWER_DOWN_REF, reg);
+}
+
+static int ad9545_calc_ftw(struct ad9545_ppl_clk *clk, u32 freq, u64 *tuning_word)
+{
+	u64 ftw = 1;
+	u32 ftw_frac;
+	u32 ftw_int;
+
+	/*
+	 * In case of unlock event the DPLL will go in open-loop mode and output
+	 * the freq given by the freerun tuning word.
+	 * DPLLx Freerun TW = (2 ^ 48) × (f NCO /f System )
+	 */
+	ftw = mul_u64_u32_div(ftw << 48, freq, clk->st->sys_clk.sys_freq_hz);
+
+	/*
+	 * Check if FTW is valid:
+	 * (2 ^ 48) / FTW = INT.FRAC where:
+	 * 7 ≤ INT ≤ 13 and 0.05 ≤ FRAC ≤ 0.95
+	 */
+	ftw_int = div64_u64(1ULL << 48, ftw);
+	if (ftw_int < 7 || ftw_int > 13)
+		return -EINVAL;
+
+	div_u64_rem(div64_u64(100 * (1ULL << 48), ftw), 100, &ftw_frac);
+	if (ftw_frac < 5 || ftw_frac > 95)
+		return -EINVAL;
+
+	*tuning_word = ftw;
+
+	return 0;
+}
+
+static int ad9545_set_freerun_freq(struct ad9545_ppl_clk *clk, u32 freq)
+{
+	__le64 regval;
+	u64 ftw;
+	int ret;
+
+	ret = ad9545_calc_ftw(clk, freq, &ftw);
+	if (ret < 0)
+		return ret;
+
+	regval = cpu_to_le64(ftw);
+	ret = regmap_bulk_write(clk->st->regmap, AD9545_DPLLX_FTW(clk->address), &regval, 6);
+	if (ret < 0)
+		return ret;
+
+	clk->free_run_freq = freq;
+	return ad9545_io_update(clk->st);
+}
+
+static u32 ad9545_calc_m_div(unsigned long rate)
+{
+	u32 m_div;
+
+	/*
+	 * PFD of APLL has input frequency limits in 162 - 350 Mghz range.
+	 * Use APLL to upconvert this freq to Ghz range.
+	 */
+	m_div = div_u64(rate, ad9545_apll_pfd_rate_ranges_hz[0] / 2 +
+			ad9545_apll_pfd_rate_ranges_hz[1] / 2);
+	m_div = clamp_t(u8, m_div, AD9545_APLL_M_DIV_MIN, AD9545_APLL_M_DIV_MAX);
+
+	return m_div;
+}
+
+static u64 ad9545_calc_pll_params(struct ad9545_ppl_clk *clk, unsigned long rate,
+				  unsigned long parent_rate, u32 *m, u32 *n,
+				  unsigned long *frac, unsigned long *mod)
+{
+	u32 min_dpll_n_div;
+	u64 output_rate;
+	u32 dpll_n_div;
+	u32 m_div;
+	u64 den;
+	u64 num;
+
+	/* half divider at output requires APLL to generate twice the frequency demanded */
+	rate *= 2;
+
+	m_div = ad9545_calc_m_div(rate);
+
+	/*
+	 * If N + FRAC / MOD = rate / (m_div * parent_rate)
+	 * and N = [rate / (m_div * past_rate)]:
+	 * We get: FRAC/MOD = (rate / (m_div * parent_rate)) - N
+	 */
+	dpll_n_div = div64_u64(rate, parent_rate * m_div);
+
+	/*
+	 * APLL has to be able to satisfy output freq bounds
+	 * thus output of DPLL has a lower bound
+	 */
+	min_dpll_n_div = div_u64(ad9545_apll_rate_ranges_hz[clk->address][0],
+				 AD9545_APLL_M_DIV_MAX * parent_rate);
+	dpll_n_div = clamp_t(u32, dpll_n_div, min_dpll_n_div, AD9545_DPLL_MAX_N);
+
+	num = rate - (dpll_n_div * m_div * parent_rate);
+	den = m_div * parent_rate;
+
+	rational_best_approximation(num, den, AD9545_DPLL_MAX_FRAC, AD9545_DPLL_MAX_MOD, frac, mod);
+	*m = m_div;
+	*n = dpll_n_div;
+
+	output_rate = mul_u64_u32_div(*frac * parent_rate, m_div, *mod);
+	output_rate += parent_rate * dpll_n_div * m_div;
+
+	return (u32)DIV_ROUND_CLOSEST(output_rate, 2);
+}
+
+static int ad9545_tdc_source_valid(struct ad9545_ppl_clk *clk, unsigned int tdc_source)
+{
+	unsigned int regval;
+	int ret;
+
+	if (tdc_source >= AD9545_MAX_REFS) {
+		ret = regmap_read(clk->st->regmap, AD9545_MISC, &regval);
+		if (ret < 0)
+			return ret;
+
+		if (tdc_source == AD9545_MAX_REFS)
+			return !(regval & AD9545_MISC_AUX_NC0_ERR_MSK);
+		else
+			return !(regval & AD9545_MISC_AUX_NC1_ERR_MSK);
+	} else {
+		ret = regmap_read(clk->st->regmap, AD9545_REFX_STATUS(tdc_source), &regval);
+		if (ret < 0)
+			return ret;
+
+		return !!(regval & AD9545_REFX_VALID_MSK);
+	}
+}
+
+static u8 ad9545_pll_get_parent(struct clk_hw *hw)
+{
+	struct ad9545_ppl_clk *clk = to_pll_clk(hw);
+	struct ad9545_dpll_profile *profile;
+	u8 best_prio = 0xFF;
+	u8 best_parent;
+	int ret;
+	int i;
+
+	ret = ad9545_io_update(clk->st);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * A DPLL will pick a parent clock depending
+	 * on the priorities and if it is a valid timestamp source.
+	 */
+	for (i = 0; i < AD9545_MAX_DPLL_PROFILES; i++) {
+		profile = &clk->profiles[i];
+		if (!profile->en)
+			continue;
+
+		ret = ad9545_tdc_source_valid(clk, profile->tdc_source);
+		if (ret < 0)
+			return clk->num_parents;
+
+		if (ret > 0 && profile->priority < best_prio) {
+			best_prio = profile->priority;
+			best_parent = profile->parent_index;
+		}
+	}
+
+	if (best_prio != 0xFF)
+		return best_parent;
+
+	return clk->num_parents;
+}
+
+static unsigned long ad9545_pll_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+	struct ad9545_ppl_clk *clk = to_pll_clk(hw);
+	unsigned long output_rate;
+	__le32 regval;
+	u32 frac;
+	u32 mod;
+	int ret;
+	u32 m;
+	u32 n;
+	int i;
+
+	m = 0;
+	ret = regmap_read(clk->st->regmap, AD9545_APLLX_M_DIV(clk->address), &m);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * If no ref is valid, pll will run in free run mode.
+	 * At this point the NCO of the DPLL will output a free run frequency
+	 * thus the output frequency of the PLL block will be:
+	 * f NCO * M-div / 2
+	 */
+	i = ad9545_pll_get_parent(hw);
+	if (i == clk->num_parents)
+		return div_u64(clk->free_run_freq * m, 2);
+
+	parent_rate = clk_hw_get_rate(clk->parents[i]);
+
+	ret = regmap_bulk_read(clk->st->regmap, AD9545_DPLLX_N_DIV(clk->address, i), &regval, 4);
+	if (ret < 0)
+		return ret;
+
+	n = le32_to_cpu(regval) + 1;
+
+	regval = 0;
+	ret = regmap_bulk_read(clk->st->regmap, AD9545_DPLLX_FRAC_DIV(clk->address, i), &regval, 3);
+	if (ret < 0)
+		return ret;
+
+	frac = le32_to_cpu(regval);
+
+	regval = 0;
+	ret = regmap_bulk_read(clk->st->regmap, AD9545_DPLLX_MOD_DIV(clk->address, i), &regval, 3);
+	if (ret < 0)
+		return ret;
+
+	mod = le32_to_cpu(regval);
+
+	/* Output rate of APLL = parent_rate * (N + (Frac / Mod)) * M */
+	output_rate = mul_u64_u32_div(frac * parent_rate, m, mod);
+	output_rate += parent_rate * n * m;
+
+	return output_rate / 2;
+}
+
+static long ad9545_pll_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+				      unsigned long *parent_rate)
+{
+	struct ad9545_ppl_clk *clk = to_pll_clk(hw);
+	unsigned long frac;
+	unsigned long mod;
+	int ret;
+	u64 ftw;
+	int i;
+	u32 m;
+	u32 n;
+
+	/* if no ref is valid, check if requested rate can be set in free run mode */
+	i = ad9545_pll_get_parent(hw);
+	if (i == clk->num_parents) {
+		/* in free run mode output freq is given by f NCO * m / 2 */
+		m = ad9545_calc_m_div(rate * 2);
+		ret = ad9545_calc_ftw(clk,  div_u64(rate * 2, m), &ftw);
+		if (ret < 0)
+			return 0;
+
+		return rate;
+	}
+
+	return ad9545_calc_pll_params(clk, rate, *parent_rate, &m, &n, &frac, &mod);
+}
+
+static int ad9545_pll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate)
+{
+	struct ad9545_ppl_clk *clk = to_pll_clk(hw);
+	unsigned long out_rate;
+	unsigned long frac;
+	unsigned long mod;
+	__le32 regval;
+	int ret;
+	u32 m;
+	u32 n;
+	int i;
+
+	/*
+	 * When setting a PLL rate, precalculate params for all enabled profiles.
+	 * At this point there may or may not be a valid reference.
+	 */
+	for (i = 0; i < clk->num_parents; i++) {
+		parent_rate = clk_hw_get_rate(clk->parents[i]);
+
+		out_rate = ad9545_calc_pll_params(clk, rate, parent_rate, &m, &n, &frac, &mod);
+		if (out_rate != rate)
+			return -EINVAL;
+
+		regval = cpu_to_le32(n - 1);
+		ret = regmap_bulk_write(clk->st->regmap, AD9545_DPLLX_N_DIV(clk->address, i),
+					&regval, 4);
+		if (ret < 0)
+			return ret;
+
+		ret = regmap_write(clk->st->regmap, AD9545_APLLX_M_DIV(clk->address), m);
+		if (ret < 0)
+			return ret;
+
+		regval = cpu_to_le32(frac);
+		ret = regmap_bulk_write(clk->st->regmap, AD9545_DPLLX_FRAC_DIV(clk->address, i),
+					&regval, 3);
+		if (ret < 0)
+			return ret;
+
+		regval = cpu_to_le32(mod);
+		ret = regmap_bulk_write(clk->st->regmap, AD9545_DPLLX_MOD_DIV(clk->address, i),
+					&regval, 3);
+		if (ret < 0)
+			return ret;
+	}
+
+	return ad9545_set_freerun_freq(clk, div_u64(rate * 2, m));
+}
+
+static const struct clk_ops ad9545_pll_clk_ops = {
+	.recalc_rate = ad9545_pll_clk_recalc_rate,
+	.round_rate = ad9545_pll_clk_round_rate,
+	.set_rate = ad9545_pll_set_rate,
+	.get_parent = ad9545_pll_get_parent,
+};
+
+static int ad9545_pll_fast_acq_setup(struct ad9545_ppl_clk *pll, int profile)
+{
+	struct ad9545_state *st = pll->st;
+	unsigned int tmp;
+	int ret;
+	u8 reg;
+	int i;
+
+	tmp = pll->profiles[profile].fast_acq_excess_bw;
+	for (i = 0; i < ARRAY_SIZE(ad9545_fast_acq_excess_bw_map); i++)
+		if (tmp == ad9545_fast_acq_excess_bw_map[i])
+			break;
+
+	if (i < ARRAY_SIZE(ad9545_fast_acq_excess_bw_map)) {
+		ret = regmap_write(st->regmap, AD9545_DPLLX_FAST_L1(pll->address, profile), i);
+		if (ret < 0)
+			return ret;
+	} else {
+		dev_err(st->dev, "Wrong fast_acq_excess_bw value for DPLL %u, profile: %d.",
+			pll->address, profile);
+		return -EINVAL;
+	}
+
+	tmp = pll->profiles[profile].fast_acq_settle_ms;
+	for (i = 0; i < ARRAY_SIZE(ad9545_fast_acq_timeout_map); i++)
+		if (tmp == ad9545_fast_acq_timeout_map[i])
+			break;
+
+	if (i == ARRAY_SIZE(ad9545_fast_acq_timeout_map)) {
+		dev_err(st->dev, "Wrong fast_acq_settle_ms value for DPLL %u, profile %d.",
+			pll->address, profile);
+		return -EINVAL;
+	}
+
+	reg = i;
+
+	tmp = pll->profiles[profile].fast_acq_timeout_ms;
+	for (i = 0; i < ARRAY_SIZE(ad9545_fast_acq_timeout_map); i++)
+		if (tmp == ad9545_fast_acq_timeout_map[i])
+			break;
+
+	if (i == ARRAY_SIZE(ad9545_fast_acq_timeout_map)) {
+		dev_err(st->dev, "Wrong fast_acq_timeout_ms value for DPLL %u, profile %d.",
+			pll->address, profile);
+		return -EINVAL;
+	}
+
+	reg |= i << 4;
+
+	ret = regmap_write(st->regmap, AD9545_DPLLX_FAST_L2(pll->address, profile), reg);
+	if (ret < 0)
+		return ret;
+
+	return regmap_write(st->regmap, AD9545_DPLLX_FAST_MODE(pll->address),
+			    pll->fast_acq_trigger_mode);
+}
+
+static int ad9545_plls_setup(struct ad9545_state *st)
+{
+	struct clk_init_data init[2] = {0};
+	struct ad9545_ppl_clk *pll;
+	struct clk_hw *hw;
+	int tdc_source;
+	__le32 regval;
+	int ret;
+	u8 reg;
+	int i;
+	int j;
+
+	st->clks[AD9545_CLK_PLL] = devm_kzalloc(st->dev, ARRAY_SIZE(ad9545_pll_clk_names) *
+						sizeof(struct clk *), GFP_KERNEL);
+	if (!st->clks[AD9545_CLK_PLL])
+		return -ENOMEM;
+
+	for (i = 0; i < 2; i++) {
+		pll = &st->pll_clks[i];
+		if (!pll->pll_used)
+			continue;
+
+		pll->st = st;
+		pll->address = i;
+
+		init[i].name = ad9545_pll_clk_names[i];
+		init[i].ops = &ad9545_pll_clk_ops;
+		init[i].num_parents = 0;
+		for (j = 0; j < AD9545_MAX_DPLL_PROFILES; j++)
+			if (pll->profiles[j].en)
+				init[i].num_parents++;
+
+		init[i].parent_hws = devm_kzalloc(st->dev, init[i].num_parents *
+						  sizeof(*init[i].parent_hws), GFP_KERNEL);
+		if (!init[i].parent_hws)
+			return -ENOMEM;
+
+		pll->num_parents = init[i].num_parents;
+		pll->parents = init[i].parent_hws;
+
+		for (j = 0; j < AD9545_MAX_DPLL_PROFILES; j++) {
+			if (!pll->profiles[j].en)
+				continue;
+
+			pll->profiles[j].parent_index = j;
+
+			/* enable pll profile */
+			reg = AD9545_EN_PROFILE_MSK |
+				FIELD_PREP(AD9545_SEL_PRIORITY_MSK, pll->profiles[j].priority);
+			ret = regmap_write(st->regmap, AD9545_DPLLX_EN(i, j), reg);
+			if (ret < 0)
+				return ret;
+
+			/* set TDC source */
+			tdc_source = pll->profiles[j].tdc_source;
+			ret = regmap_write(st->regmap, AD9545_DPLLX_SOURCE(i, j),
+					   ad9545_tdc_source_mapping[tdc_source]);
+			if (ret < 0)
+				return ret;
+
+			regval = cpu_to_le32(pll->profiles[j].loop_bw_uhz);
+			ret = regmap_bulk_write(st->regmap, AD9545_DPLLX_LOOP_BW(i, j), &regval, 4);
+			if (ret < 0)
+				return ret;
+
+			if (pll->profiles[j].tdc_source >= ARRAY_SIZE(ad9545_ref_clk_names))
+				hw = &st->aux_nco_clks[tdc_source - ARRAY_SIZE(ad9545_ref_clk_names)].hw;
+			else
+				hw = &st->ref_in_clks[tdc_source].hw;
+			init[i].parent_hws[j] = hw;
+
+			if (pll->profiles[j].fast_acq_excess_bw > 0) {
+				ret = ad9545_pll_fast_acq_setup(pll, j);
+				if (ret < 0)
+					return ret;
+			}
+		}
+
+		pll->hw.init = &init[i];
+		ret = devm_clk_hw_register(st->dev, &pll->hw);
+		if (ret < 0)
+			return ret;
+
+		st->clks[AD9545_CLK_PLL][i] = pll->hw.clk;
+	}
+
+	return 0;
+}
+
+static int ad9545_get_nco_freq(struct ad9545_state *st, int addr, u32 *freq)
+{
+	__le16 regval;
+	int ret;
+
+	ret = regmap_bulk_read(st->regmap, AD9545_NCOX_FREQ(addr), &regval, 2);
+	if (ret < 0)
+		return ret;
+
+	*freq = le16_to_cpu(regval);
+	return 0;
+}
+
+static int ad9545_set_nco_freq(struct ad9545_state *st, int addr, u32 freq)
+{
+	__le32 regval;
+	int ret;
+
+	regval = cpu_to_le32(freq);
+	ret = regmap_bulk_write(st->regmap, AD9545_NCOX_FREQ(addr), &regval, 2);
+	if (ret < 0)
+		return ret;
+
+	return ad9545_io_update(st);
+}
+
+static unsigned long ad95452_nco_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+	struct ad9545_aux_nco_clk *clk = to_nco_clk(hw);
+	u32 rate;
+	int ret;
+
+	ret = ad9545_get_nco_freq(clk->st, clk->address, &rate);
+	if (ret < 0) {
+		dev_err(clk->st->dev, "Could not read NCO freq.");
+		return 0;
+	}
+
+	return rate;
+}
+
+static long ad9545_nco_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+				      unsigned long *parent_rate)
+{
+	return clamp_t(u16, rate, 1, AD9545_NCO_MAX_FREQ);
+}
+
+static int ad9545_nco_clk_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate)
+{
+	struct ad9545_aux_nco_clk *clk = to_nco_clk(hw);
+
+	return ad9545_set_nco_freq(clk->st, clk->address, rate);
+}
+
+static const struct clk_ops ad9545_nco_clk_ops = {
+	.recalc_rate = ad95452_nco_clk_recalc_rate,
+	.round_rate = ad9545_nco_clk_round_rate,
+	.set_rate = ad9545_nco_clk_set_rate,
+};
+
+static int ad9545_aux_ncos_setup(struct ad9545_state *st)
+{
+	struct clk_init_data init[2] = {0};
+	struct ad9545_aux_nco_clk *nco;
+	__le32 regval;
+	int ret;
+	int i;
+
+	st->clks[AD9545_CLK_NCO] = devm_kzalloc(st->dev, ARRAY_SIZE(ad9545_aux_nco_clk_names) *
+						sizeof(struct clk *), GFP_KERNEL);
+	if (!st->clks[AD9545_CLK_NCO])
+		return -ENOMEM;
+
+	for (i = 0; i < ARRAY_SIZE(st->aux_nco_clks); i++) {
+		nco = &st->aux_nco_clks[i];
+		if (!nco->nco_used)
+			continue;
+
+		regval = cpu_to_le32(nco->freq_thresh_ps);
+		ret = regmap_bulk_write(st->regmap, AD9545_NCOX_FREQ_THRESH(i), &regval, 3);
+		if (ret < 0)
+			return ret;
+
+		regval = cpu_to_le32(nco->phase_thresh_ps);
+		ret = regmap_bulk_write(st->regmap, AD9545_NCOX_PHASE_THRESH(i), &regval, 3);
+		if (ret < 0)
+			return ret;
+
+		init[i].name = ad9545_aux_nco_clk_names[i];
+		init[i].ops = &ad9545_nco_clk_ops;
+
+		nco->hw.init = &init[i];
+		ret = devm_clk_hw_register(st->dev, &nco->hw);
+		if (ret < 0)
+			return ret;
+
+		st->clks[AD9545_CLK_NCO][i] = nco->hw.clk;
+	}
+
+	return 0;
+}
+
+static int ad9545_set_tdc_div(struct ad9545_aux_tdc_clk *clk, u32 div)
+{
+	int ret;
+
+	if (!div)
+		return -EINVAL;
+
+	ret = regmap_write(clk->st->regmap, AD9545_TDCX_DIV(clk->address), --div);
+	if (ret < 0)
+		return ret;
+
+	return ad9545_io_update(clk->st);
+}
+
+static unsigned long ad9545_tdc_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+	struct ad9545_aux_tdc_clk *clk = to_tdc_clk(hw);
+	int ret;
+	u32 div;
+
+	ret = regmap_read(clk->st->regmap, AD9545_TDCX_DIV(clk->address), &div);
+	if (ret < 0) {
+		dev_err(clk->st->dev, "Could not read TDC freq.");
+		return ret;
+	}
+
+	div++;
+
+	return DIV_ROUND_UP_ULL((u64)parent_rate, div);
+}
+
+static long ad9545_tdc_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+				      unsigned long *parent_rate)
+{
+	u32 div;
+
+	if (!*parent_rate || !rate)
+		return 0;
+
+	div = clamp_t(u8, DIV_ROUND_UP_ULL((u64)*parent_rate, rate), 1, U8_MAX);
+
+	return DIV_ROUND_UP_ULL((u64)*parent_rate, div);
+}
+
+static int ad9545_tdc_clk_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate)
+{
+	struct ad9545_aux_tdc_clk *clk = to_tdc_clk(hw);
+	__le64 regval64;
+	u64 period_es;
+	u32 div;
+	int ret;
+
+	if (!parent_rate || !rate)
+		return 0;
+
+	/* write parent rate received at the Mx pin in attoseconds */
+	period_es = div_u64(1000000000000000000ULL, parent_rate);
+	regval64 = cpu_to_le64(period_es);
+	ret = regmap_bulk_write(clk->st->regmap, AD9545_TDCX_PERIOD(clk->address), &regval64, 8);
+	if (ret < 0)
+		return ret;
+
+	div = clamp_t(u8, DIV_ROUND_UP_ULL((u64)parent_rate, rate), 1, U8_MAX);
+
+	return ad9545_set_tdc_div(clk, div);
+}
+
+static const struct clk_ops ad9545_aux_tdc_clk_ops = {
+	.recalc_rate = ad9545_tdc_clk_recalc_rate,
+	.round_rate = ad9545_tdc_clk_round_rate,
+	.set_rate = ad9545_tdc_clk_set_rate,
+};
+
+static int ad9545_aux_tdcs_setup(struct ad9545_state *st)
+{
+	struct clk_init_data init[ARRAY_SIZE(ad9545_aux_tdc_clk_names)] = {0};
+	struct ad9545_aux_tdc_clk *tdc;
+	int ret;
+	int i;
+
+	st->clks[AD9545_CLK_AUX_TDC] = devm_kcalloc(st->dev, ARRAY_SIZE(ad9545_aux_tdc_clk_names),
+						    sizeof(*st->clks[AD9545_CLK_AUX_TDC]),
+						    GFP_KERNEL);
+	if (!st->clks[AD9545_CLK_AUX_TDC])
+		return -ENOMEM;
+
+	for (i = 0; i < ARRAY_SIZE(st->aux_tdc_clks); i++) {
+		tdc = &st->aux_tdc_clks[i];
+		if (!tdc->tdc_used)
+			continue;
+
+		/* redirect Mx pin to this TDC */
+		ret = regmap_write(st->regmap, AD9545_MX_PIN(tdc->pin_nr),
+				   AD9545_MX_TO_TDCX(tdc->address));
+		if (ret < 0)
+			return ret;
+
+		init[i].name = ad9545_aux_tdc_clk_names[i];
+		init[i].ops = &ad9545_aux_tdc_clk_ops;
+		init[i].parent_names = &ad9545_ref_m_clk_names[tdc->pin_nr];
+		init[i].num_parents = 1;
+		tdc->hw.init = &init[i];
+		ret = devm_clk_hw_register(st->dev, &tdc->hw);
+		if (ret < 0)
+			return ret;
+
+		st->clks[AD9545_CLK_AUX_TDC][i] = tdc->hw.clk;
+	}
+
+	return 0;
+}
+
+static unsigned long ad9545_aux_dpll_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+	return parent_rate;
+}
+
+static const struct clk_ops ad9545_aux_dpll_clk_ops = {
+	.recalc_rate = ad9545_aux_dpll_clk_recalc_rate,
+};
+
+static int ad9545_aux_dpll_setup(struct ad9545_state *st)
+{
+	struct ad9545_aux_dpll_clk *clk;
+	struct clk_init_data init;
+	__le16 regval;
+	int ret;
+	u32 val;
+	int i;
+
+	clk = &st->aux_dpll_clk;
+	if (!clk->dpll_used)
+		return 0;
+
+	memset(&init, 0, sizeof(struct clk_init_data));
+
+	if (clk->source < ARRAY_SIZE(ad9545_in_clk_names)) {
+		val = clk->source;
+		init.parent_names = &ad9545_in_clk_names[val];
+	} else {
+		val = clk->source - ARRAY_SIZE(ad9545_in_clk_names);
+		if (val > ARRAY_SIZE(ad9545_aux_tdc_clk_names))
+			return -EINVAL;
+		init.parent_names = &ad9545_aux_tdc_clk_names[val];
+		val = val + 0x6;
+	}
+
+	ret = regmap_write(st->regmap, AD9545_AUX_DPLL_SOURCE, val);
+	if (ret < 0)
+		return ret;
+
+	/* write loop bandwidth in dHz */
+	regval = cpu_to_le16(clk->loop_bw_mhz / 100);
+	ret = regmap_bulk_write(st->regmap, AD9545_AUX_DPLL_LOOP_BW, &regval, 2);
+	if (ret < 0)
+		return ret;
+
+	val = 0;
+	for (i = 0; i < ARRAY_SIZE(ad9545_rate_change_limit_map); i++) {
+		if (ad9545_rate_change_limit_map[i] == clk->rate_change_limit) {
+			val = i;
+			break;
+		}
+	}
+
+	ret = regmap_write(st->regmap, AD9545_AUX_DPLL_CHANGE_LIMIT, val);
+	if (ret < 0)
+		return ret;
+
+	/* add compensation destination */
+	ret = regmap_write(st->regmap, AD9545_COMPENSATE_DPLL, AD9545_COMPNESATE_VIA_AUX_DPLL);
+	if (ret < 0)
+		return ret;
+
+	ret = regmap_write(st->regmap, AD9545_COMPENSATE_TDCS, AD9545_COMPENSATE_TDCS_VIA_AUX_DPLL);
+	if (ret < 0)
+		return ret;
+
+	init.name = ad9545_aux_dpll_name;
+	init.ops = &ad9545_aux_dpll_clk_ops;
+	init.num_parents = 1;
+
+	clk->hw.init = &init;
+	return devm_clk_hw_register(st->dev, &clk->hw);
+}
+
+static int ad9545_calib_system_clock(struct ad9545_state *st)
+{
+	int ret;
+	u32 reg;
+	int i;
+	int j;
+
+	for (i = 0; i < 2; i++) {
+		for (j = 0; j < ARRAY_SIZE(ad9545_vco_calibration_op); j++) {
+			ret = regmap_write(st->regmap, ad9545_vco_calibration_op[j][0],
+					   ad9545_vco_calibration_op[j][1]);
+			if (ret < 0)
+				return ret;
+		}
+
+		/* wait for sys pll to lock and become stable */
+		msleep(50 + AD9545_SYS_CLK_STABILITY_MS);
+
+		ret = regmap_read(st->regmap, AD9545_PLL_STATUS, &reg);
+		if (ret < 0)
+			return ret;
+
+		if (AD9545_SYS_PLL_STABLE(reg)) {
+			ret = regmap_write(st->regmap, AD9545_CALIB_CLK, 0);
+			if (ret < 0)
+				return ret;
+
+			return ad9545_io_update(st);
+		}
+	}
+
+	dev_err(st->dev, "System PLL unlocked.\n");
+	return -EIO;
+}
+
+static int ad9545_calib_apll(struct ad9545_state *st, int i)
+{
+	int cal_count;
+	u32 reg;
+	int ret;
+
+	/* APLL VCO calibration operation */
+	cal_count = 0;
+	while (cal_count < 2) {
+		ret = regmap_write(st->regmap, AD9545_PWR_CALIB_CHX(i), 0);
+		if (ret < 0)
+			return ret;
+
+		ret = ad9545_io_update(st);
+		if (ret < 0)
+			return ret;
+
+		ret = regmap_write(st->regmap, AD9545_PWR_CALIB_CHX(i),
+				   AD9545_CALIB_APLL);
+		if (ret < 0)
+			return ret;
+
+		ret = ad9545_io_update(st);
+		if (ret < 0)
+			return ret;
+
+		cal_count += 1;
+		msleep(100);
+
+		ret = regmap_read(st->regmap, AD9545_PLLX_STATUS(i), &reg);
+		if (ret < 0)
+			return ret;
+
+		if (AD9545_APLL_LOCKED(reg)) {
+			ret = regmap_write(st->regmap, AD9545_PWR_CALIB_CHX(i), 0);
+			if (ret < 0)
+				return ret;
+
+			ret = ad9545_io_update(st);
+			if (ret < 0)
+				return ret;
+
+			cal_count = 2;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int ad9545_calib_aplls(struct ad9545_state *st)
+{
+	int ret;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ad9545_pll_clk_names); i++) {
+		if (!st->pll_clks[i].pll_used)
+			continue;
+
+		ret = ad9545_calib_apll(st, i);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static struct clk *ad9545_clk_src_twocell_get(struct of_phandle_args *clkspec, void *data)
+{
+	unsigned int clk_address = clkspec->args[1];
+	unsigned int clk_type = clkspec->args[0];
+	struct clk ***clks = data;
+
+	if (clk_type > AD9545_CLK_AUX_TDC) {
+		pr_err("%s: invalid clock type %u\n", __func__, clk_type);
+		return ERR_PTR(-EINVAL);
+	}
+	if ((clk_type == AD9545_CLK_PLL && clk_address > AD9545_PLL1) ||
+	    (clk_type == AD9545_CLK_OUT && clk_address > AD9545_Q1BB) ||
+	    (clk_type == AD9545_CLK_NCO && clk_address > AD9545_NCO1) ||
+	    (clk_type == AD9545_CLK_AUX_TDC && clk_address > AD9545_CLK_AUX_TDC1)) {
+		pr_err("%s: invalid clock address %u\n", __func__, clk_address);
+		return ERR_PTR(-EINVAL);
+	}
+
+	return clks[clk_type][clk_address];
+}
+
+static int ad9545_setup(struct ad9545_state *st)
+{
+	int ret;
+	u32 val;
+	int i;
+
+	ret = regmap_update_bits(st->regmap, AD9545_CONFIG_0, AD9545_RESET_REGS, AD9545_RESET_REGS);
+	if (ret < 0)
+		return ret;
+
+	ret = ad9545_sys_clk_setup(st);
+	if (ret < 0)
+		return ret;
+
+	ret = ad9545_input_refs_setup(st);
+	if (ret < 0)
+		return ret;
+
+	ret = ad9545_aux_ncos_setup(st);
+	if (ret < 0)
+		return ret;
+
+	ret = ad9545_calib_system_clock(st);
+	if (ret < 0)
+		return ret;
+
+	ret = ad9545_aux_tdcs_setup(st);
+	if (ret < 0)
+		return ret;
+
+	ret = ad9545_aux_dpll_setup(st);
+	if (ret < 0)
+		return ret;
+
+	ret = ad9545_calib_aplls(st);
+	if (ret < 0)
+		return ret;
+
+	ret = ad9545_io_update(st);
+	if (ret < 0)
+		return ret;
+
+	ret = ad9545_plls_setup(st);
+	if (ret < 0)
+		return ret;
+
+	ret = ad9545_outputs_setup(st);
+	if (ret < 0)
+		return ret;
+
+	ret = of_clk_add_provider(st->dev->of_node, ad9545_clk_src_twocell_get,
+				  &st->clks[AD9545_CLK_OUT]);
+	if (ret < 0)
+		return ret;
+
+	ret = ad9545_calib_aplls(st);
+	if (ret < 0)
+		return ret;
+
+	/* check locks */
+	ret = regmap_read(st->regmap, AD9545_PLL_STATUS, &val);
+	for (i = 0; i < ARRAY_SIZE(st->pll_clks); i++)
+		if (st->pll_clks[i].pll_used && !AD9545_PLLX_LOCK(i, val))
+			dev_warn(st->dev, "PLL%d unlocked.\n", i);
+
+	if (st->aux_dpll_clk.dpll_used) {
+		ret = regmap_read(st->regmap, AD9545_MISC, &val);
+		if (ret < 0)
+			return ret;
+
+		if (!(val & AD9545_AUX_DPLL_LOCK_MSK))
+			dev_warn(st->dev, "Aux DPLL unlocked.\n");
+
+		if (val & AD9545_AUX_DPLL_REF_FAULT)
+			dev_warn(st->dev, "Aux DPLL reference fault.\n");
+	}
+
+	return 0;
+}
+
+int ad9545_probe(struct device *dev, struct regmap *regmap)
+{
+	struct ad9545_state *st;
+	int ret;
+
+	st = devm_kzalloc(dev, sizeof(struct ad9545_state), GFP_KERNEL);
+	if (!st)
+		return -ENOMEM;
+
+	st->dev = dev;
+	st->regmap = regmap;
+
+	ret = ad9545_check_id(st);
+	if (ret < 0)
+		return ret;
+
+	ret = ad9545_parse_dt(st);
+	if (ret < 0)
+		return ret;
+
+	return ad9545_setup(st);
+}
+EXPORT_SYMBOL_GPL(ad9545_probe);
+
+MODULE_AUTHOR("Alexandru Tachici <alexandru.tachici@analog.com>");
+MODULE_DESCRIPTION("Analog Devices AD9545");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/clk/adi/clk-ad9545.h b/drivers/clk/adi/clk-ad9545.h
new file mode 100644
index 000000000000..641acabe9c8e
--- /dev/null
+++ b/drivers/clk/adi/clk-ad9545.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * AD9545 Network Clock Generator/Synchronizer
+ *
+ * Copyright 2020 Analog Devices Inc.
+ */
+
+#ifndef _CLK_AD9545_H_
+#define _CLK_AD9545_H_
+
+struct device;
+struct regmap;
+
+int ad9545_probe(struct device *dev, struct regmap *regmap);
+
+#endif /* _CLK_AD9545_H_ */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 2/2] dt-bindings: clock: ad9545: Add documentation
  2021-06-14  7:07 [PATCH v2 0/2] clk: ad9545: Add support alexandru.tachici
  2021-06-14  7:07 ` [PATCH v2 1/2] " alexandru.tachici
@ 2021-06-14  7:07 ` alexandru.tachici
  2021-06-14 13:39   ` Rob Herring
                     ` (5 more replies)
  1 sibling, 6 replies; 9+ messages in thread
From: alexandru.tachici @ 2021-06-14  7:07 UTC (permalink / raw)
  To: linux-clk, linux-kernel, devicetree
  Cc: robh+dt, sboyd, mturquette, petre.minciunescu, Alexandru Tachici

From: Alexandru Tachici <alexandru.tachici@analog.com>

Add dt bindings for ad9545.

Signed-off-by: Alexandru Tachici <alexandru.tachici@analog.com>
---
 .../devicetree/bindings/clock/clk-ad9545.yaml | 556 ++++++++++++++++++
 include/dt-bindings/clock/ad9545.h            |  69 +++
 2 files changed, 625 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/clk-ad9545.yaml
 create mode 100644 include/dt-bindings/clock/ad9545.h

diff --git a/Documentation/devicetree/bindings/clock/clk-ad9545.yaml b/Documentation/devicetree/bindings/clock/clk-ad9545.yaml
new file mode 100644
index 000000000000..50553a88ab44
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/clk-ad9545.yaml
@@ -0,0 +1,556 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/clk-ad9545.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices AD9545 Quad Input, 10-Output, Dual DPLL/IEEE 1588
+
+maintainers:
+  - Alexandru Tachici <alexandru.tachici@analog.com>
+
+description: |
+  Analog Devices AD9545 Quad Input, 10-Output, Dual DPLL/IEEE 1588,
+  1 pps Synchronizer and Jitter Cleaner
+  https://www.analog.com/media/en/technical-documentation/data-sheets/ADM1266.pdf
+
+properties:
+  compatible:
+    enum:
+      - adi,ad9545
+
+  "#clock-cells":
+    const: 2
+
+  reg:
+    description: |
+      I2C address of the secondary device.
+    minimum: 0
+    maximum: 0xFF
+
+  avcc-supply:
+    description: |
+      Phandle to the Avcc power supply.
+
+  adi,freq-doubler:
+    description: |
+      The system clock PLL provides the user with the option of doubling the reference frequency.
+    type: boolean
+
+  adi,ref-crystal:
+    description: |
+      At XOA,XOB there is a crystal connected that needs maintaining.
+      Otherwise it is assumed that there is a TCXO or OCXO connected.
+    type: boolean
+
+  adi,ref-frequency-hz:
+    description: |
+      Reference input frequency at XOA,XOB. This is used for the system clock.
+
+  clocks:
+    items:
+      - description: Ref A clock input
+      - description: Ref AA clock input
+      - description: Ref B clock input
+      - description: Ref BB clock input
+      - description: Ref M0 clock input
+      - description: Ref M1 clock input
+      - description: Ref M2 clock input
+    maxItems: 4
+
+  assigned-clocks:
+    description:
+      Clocks are identified using two cells <&ad9545 clock_type clock_address>.
+    minItems: 1
+    maxItems: 14
+
+  assigned-clock-rates:
+    minItems: 1
+    maxItems: 14
+
+  assigned-clock-phases:
+    minItems: 1
+    maxItems: 14
+
+  clock-output-names:
+    maxItems: 10
+
+  aux-dpll:
+    description: |
+      Auxiliary DPLL used for Closed-Loop method of system clock compensation.
+    type: object
+
+    properties:
+      adi,compensation-source:
+        description: |
+          System clock closed loop compensation source.
+          Choose from Ref-A to Ref-BB [0-3] or aux TDCs [4-5].
+        $ref: /schemas/types.yaml#/definitions/uint32
+        enum: [0, 1, 2, 3, 4, 5]
+
+      adi,aux-dpll-bw-mhz:
+        description: |
+          Auxiliary DPLL bandwidth.
+        minimum: 100
+        maximum: 2000000
+
+      adi,rate-change-limit:
+        description: |
+          Error compensation rate change limiting expressed in ppb/s. Disabled if property is
+          missing.
+        $ref: /schemas/types.yaml#/definitions/uint32
+        enum: [715, 1430, 2860, 5720, 11440, 22880, 45760]
+
+    required:
+      - adi,compensation-source
+      - adi,aux-dpll-bw-mhz
+
+  aux-tdc-clks:
+    description: |
+      Child nodes represent Mx pin reference clock inputs.
+    type: object
+
+    properties:
+      '#address-cells':
+         const: 1
+
+      '#size-cells':
+         const: 0
+
+    patternProperties:
+      "^aux-tdc-clk@[0-3]$":
+
+        description: |
+          Represents a Mx pin reference clock input.
+        type: object
+
+        properties:
+          reg:
+            description: |
+              Address of the Auxiliary TDC.
+            maximum: 1
+
+          adi,pin-nr:
+            description: |
+              Pin number to be the source of this TDC.
+            $ref: /schemas/types.yaml#/definitions/uint32
+            minimum: 0
+            maximum: 6
+
+        required:
+          - reg
+          - adi,pin-nr
+
+    additionalProperties: false
+
+  ref-input-clks:
+    description: |
+      Child nodes represent reference clock inputs.
+    type: object
+
+    properties:
+      '#address-cells':
+         const: 1
+
+      '#size-cells':
+         const: 0
+
+    patternProperties:
+      "^ref-input-clk@[0-3]$":
+        description: |
+          Represents a reference clock input.
+        type: object
+
+        properties:
+          reg:
+            description: |
+              The reference input number. It can have up to 4 input clocks numbered from 0 to 3.
+              (mapped: [refa, refaa, refb, refbb] -> [0, 1, 2, 3])
+            maxItems: 1
+
+          adi,single-ended-mode:
+            description: |
+              Single-ended configuration mode.
+            $ref: /schemas/types.yaml#/definitions/uint32
+            enum: [0, 1, 2, 3]
+
+          adi,differential-mode:
+            description: |
+              Differential configuration mode.
+            $ref: /schemas/types.yaml#/definitions/uint32
+            enum: [0, 1, 2]
+
+          adi,r-divider-ratio:
+            description: |
+              Each reference input has a dedicated divider.
+            $ref: /schemas/types.yaml#/definitions/uint32
+            minimum: 1
+            maximum: 1073741824
+
+          adi,ref-dtol-pbb:
+            description: |
+              REFx offset limit. Constitutes a fractional portion of the corresponding nominal period.
+              The 24-bit number represents fractional units of parts per billion (ppb) up to a
+              maximum of approximately 17 million ppb (1.7%).
+            $ref: /schemas/types.yaml#/definitions/uint32
+            minimum: 0
+            maximum: 16777215
+            default: 100000
+
+          adi,ref-monitor-hysteresis-pbb:
+            description: |
+              Basis points of the offset limit representing per ten thousand of REFx offset limit.
+            $ref: /schemas/types.yaml#/definitions/uint32
+            enum: [0, 3125, 6250, 12500, 25000, 50000, 75000, 87500]
+            default: 12500
+
+          adi,ref-validation-timer-ms:
+            description: |
+              Time required for a reference to remain in tolerance condition before being
+              available to be used.
+            $ref: /schemas/types.yaml#/definitions/uint32
+            minimum: 1
+            maximum: 1048574
+            default: 10
+
+          adi,freq-lock-threshold-ps:
+            description: |
+              Phase lock detector threshold (in picoseconds).
+            $ref: /schemas/types.yaml#/definitions/uint32
+            minimum: 1
+            maximum: 16777215
+
+          adi,phase-lock-threshold-ps:
+            description: |
+              Profile 0 frequency lock threshold. Frequency lock detector threshold (in picoseconds).
+            $ref: /schemas/types.yaml#/definitions/uint32
+            minimum: 1
+            maximum: 16777215
+
+          adi,phase-lock-fill-rate:
+            description: |
+              Parameter used by the DPLL Phase Lock Detector.
+            $ref: /schemas/types.yaml#/definitions/uint32
+            minimum: 1
+            maximum: 255
+            default: 10
+
+          adi,phase-lock-drain-rate:
+            description: |
+              Parameter used by the DPLL Phase Lock Detector.
+            $ref: /schemas/types.yaml#/definitions/uint32
+            minimum: 1
+            maximum: 255
+            default: 10
+
+          adi,freq-lock-fill-rate:
+            description: |
+              Parameter used by the DPLL Frequency Lock Detector.
+            $ref: /schemas/types.yaml#/definitions/uint32
+            minimum: 1
+            maximum: 255
+            default: 10
+
+          adi,freq-lock-drain-rate:
+            description: |
+              Parameter used by the DPLL Frequency Lock Detector.
+            $ref: /schemas/types.yaml#/definitions/uint32
+            minimum: 1
+            maximum: 255
+            default: 10
+
+        required:
+          - reg
+          - adi,r-divider-ratio
+          - adi,ref-dtol-pbb
+          - adi,ref-monitor-hysteresis-pbb
+          - adi,ref-validation-timer-ms
+          - adi,freq-lock-threshold-ps
+          - adi,phase-lock-threshold-ps
+
+    additionalProperties: false
+
+  pll-clks:
+    description: |
+      Child nodes represent PLLs.
+    type: object
+
+    properties:
+      '#address-cells':
+         const: 1
+
+      '#size-cells':
+         const: 0
+
+    patternProperties:
+      "^pll-clk@[0-1]$":
+        description: |
+          Represents a PLL.
+        type: object
+
+        properties:
+          reg:
+            description: |
+              PLL number. AD9545 has two PLLs.
+            maxItems: 1
+
+          '#address-cells':
+             const: 1
+
+          '#size-cells':
+             const: 0
+
+          adi,fast-acq-trigger-mode:
+            description: |
+              If this is not specified Fast Acquisition will be used every time. See reg 0x2106
+              for constraints on Fast Acquisition trigger.
+            $ref: /schemas/types.yaml#/definitions/uint32
+            minimum: 0
+            maximum: 15
+            default: 0
+
+        patternProperties:
+          "^profile@[0-5]$":
+            description: |
+              Represents a DPLL profile. Each DPLL can have up to 6 specified sources
+              wih priorities assigned.
+            type: object
+
+            properties:
+              reg:
+                description: |
+                  Profile number. A DPLL can have up to 6 translation profiles.
+                maxItems: 1
+              adi,profile-priority:
+                description: |
+                  Profile selection priority. 0 is the highest, 31 is the lowest. For revertive
+                  reference switching, ensure that priority difference is > 7.
+                $ref: /schemas/types.yaml#/definitions/uint32
+                minimum: 0
+                maximum: 31
+
+              adi,pll-source:
+                description: |
+                  Each PLL can have 1 signal source. Choose from Ref-A to Ref-BB [0-3] or aux NCOs [4-5].
+                $ref: /schemas/types.yaml#/definitions/uint32
+                enum: [0, 1, 2, 3, 4, 5]
+
+              adi,pll-loop-bandwidth-uhz:
+                description: |
+                  PLL loop bandwidth in microhertz.
+                $ref: /schemas/types.yaml#/definitions/uint32
+                minimum: 1
+                maximum: 1850000000
+                default: 200000000
+
+              adi,fast-acq-excess-bw:
+                description: |
+                  Controls the DPLL loop bandwidth scaling factor while in fast acquisition mode.
+                  0 means this feature is disabled.
+                $ref: /schemas/types.yaml#/definitions/uint32
+                enum: [0, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]
+                default: 0
+
+              adi,fast-acq-timeout-ms:
+                description: |
+                  Fast acquisition timeout controls the maximum amount of time that DPLL waits to
+                  achieve phase lock before reducing the loop bandwidth by a factor of two.
+                $ref: /schemas/types.yaml#/definitions/uint32
+                enum: [1, 10, 50, 100, 500, 1000, 10000, 50000]
+                default: 1
+
+              adi,fast-acq-lock-settle-ms:
+                description: |
+                  Controls how long DPLL must wait after achieving phase lock before reducing
+                  the loop bandwidth by a factor of 2.
+                $ref: /schemas/types.yaml#/definitions/uint32
+                enum: [1, 10, 50, 100, 500, 1000, 10000, 50000]
+                default: 1
+
+            required:
+              - reg
+              - adi,pll-source
+              - adi,pll-loop-bandwidth-uhz
+
+        additionalProperties: false
+
+        required:
+          - reg
+
+    additionalProperties: false
+
+  aux-ncos:
+    description: |
+      Child nodes represent auxiliary Numerical Controlled Oscilators.
+    type: object
+
+    properties:
+      '#address-cells':
+         const: 1
+
+      '#size-cells':
+         const: 0
+
+    patternProperties:
+      "^aux-nco-clk@[0-1]$":
+        description: |
+          Represents an auxiliary Numerical Controlled Oscilator. Generates timestamps that
+          can be sent to the DPLL0 or DPLL1.
+        type: object
+
+        properties:
+          reg:
+            description: |
+              Auxiliary NCO address mapped: [NCO0, NCO1] -> [0, 1].
+            maxItems: 1
+
+          adi,freq-lock-threshold-ps:
+            description: |
+              Phase lock detector threshold (in picoseconds).
+            $ref: /schemas/types.yaml#/definitions/uint32
+            minimum: 1
+            maximum: 16777215
+
+          adi,phase-lock-threshold-ps:
+            description: |
+              Profile 0 frequency lock threshold. Frequency lock detector threshold (in picoseconds).
+            $ref: /schemas/types.yaml#/definitions/uint32
+            minimum: 1
+            maximum: 16777215
+
+        required:
+          - reg
+          - adi,freq-lock-threshold-ps
+          - adi,phase-lock-threshold-ps
+
+    additionalProperties: false
+
+  output-clks:
+    description: |
+      Child nodes represent clock outputs.
+    type: object
+
+    properties:
+      '#address-cells':
+         const: 1
+
+      '#size-cells':
+         const: 0
+
+    patternProperties:
+      "^output-clk@([0-9]|1[0-3])$":
+        description: |
+          Represents a clock output.
+        type: object
+
+        properties:
+          reg:
+            description: |
+              The reference input number. It can have up to 10 output clocks mapped:
+              (OUT0AP OUT0AN OUT0BP OUT0BN OUT0CP OUT0CN OUT1AP OUT1AN OUT1BP OUT1BN) ->
+              (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
+            maxItems: 1
+
+          adi,current-source:
+            description: |
+              If specified output is set as current source.
+            type: boolean
+
+          adi,current-source-microamp:
+            description: |
+              The magnitude of the driver current.
+            $ref: /schemas/types.yaml#/definitions/uint32
+            enum: [7500, 12500, 15000]
+
+          adi,output-mode:
+            description: |
+              Output driver mode.
+            $ref: /schemas/types.yaml#/definitions/uint32
+            enum: [0, 1, 2]
+
+        required:
+          - reg
+          - adi,current-source-microamp
+          - adi,output-mode
+
+    additionalProperties: false
+
+required:
+  - compatible
+  - reg
+  - adi,ref-frequency-hz
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/ad9545.h>
+
+    i2c1 {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        ad9545_clock: ad9545@4A {
+                compatible = "adi,ad9545";
+                reg = <0x4A>;
+
+                adi,ref-crystal;
+                adi,ref-frequency-hz = <52000000>;
+
+                #clock-cells = <2>;
+                assigned-clocks = <&ad9545_clock AD9545_CLK_NCO AD9545_NCO0>,
+                                  <&ad9545_clock AD9545_CLK_PLL AD9545_PLL1>,
+                                  <&ad9545_clock AD9545_CLK_OUT AD9545_Q1A>,
+                                  <&ad9545_clock AD9545_CLK_OUT AD9545_Q1B>;
+                assigned-clock-rates = <10000>, <1875000000>, <156250000>, <156250000>;
+                assigned-clock-phases = <0>, <0>, <0>, <180>;
+
+                aux-ncos {
+                        #address-cells = <1>;
+                        #size-cells = <0>;
+
+                        aux-nco-clk@AD9545_NCO0 {
+                                reg = <AD9545_NCO0>;
+                                adi,freq-lock-threshold-ps = <16000000>;
+                                adi,phase-lock-threshold-ps = <16000000>;
+                        };
+                };
+
+                pll-clks {
+                        #address-cells = <1>;
+                        #size-cells = <0>;
+
+                        ad9545_apll1: pll-clk@AD9545_PLL1 {
+                                reg = <AD9545_PLL1>;
+
+                                #address-cells = <1>;
+                                #size-cells = <0>;
+
+                                profile@0 {
+                                       reg = <0>;
+                                       adi,pll-source = <4>;
+                                       adi,profile-priority = <0>;
+                                       adi,pll-loop-bandwidth-uhz = <200000000>;
+                                };
+                        };
+                };
+
+                output-clks {
+                        #address-cells = <1>;
+                        #size-cells = <0>;
+
+                        output-clk@AD9545_Q1A {
+                                reg = <AD9545_Q1A>;
+                                adi,output-mode = <DRIVER_MODE_DUAL_DIV>;
+                                adi,current-source-microamp = <15000>;
+                        };
+
+                        output-clk@AD9545_Q1B {
+                                reg = <AD9545_Q1B>;
+                                adi,output-mode = <DRIVER_MODE_DUAL_DIV>;
+                                adi,current-source-microamp = <15000>;
+                        };
+                };
+        };
+    };
+...
diff --git a/include/dt-bindings/clock/ad9545.h b/include/dt-bindings/clock/ad9545.h
new file mode 100644
index 000000000000..857d50e5715b
--- /dev/null
+++ b/include/dt-bindings/clock/ad9545.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * AD9545 Network Clock Generator/Synchronizer
+ *
+ * Copyright 2020 Analog Devices Inc.
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_AD9545_H_
+#define _DT_BINDINGS_CLOCK_AD9545_H_
+
+/* Input Driver Mode
+ * Use for adi,single-ended-mode:
+ */
+#define DRIVER_MODE_AC_COUPLED_IF	0
+#define DRIVER_MODE_DC_COUPLED_1V2	1
+#define DRIVER_MODE_DC_COUPLED_1V8	2
+#define DRIVER_MODE_IN_PULL_UP		3
+
+/* Input Driver Mode
+ * Use for adi,differential-mode:
+ */
+#define DRIVER_MODE_AC_COUPLED		0
+#define DRIVER_MODE_DC_COUPLED		1
+#define DRIVER_MODE_DC_COUPLED_LVDS	2
+
+/* Output Driver Mode
+ * Use for adi,output-mode:
+ */
+#define DRIVER_MODE_SINGLE_DIV_DIF	0
+#define DRIVER_MODE_SINGLE_DIV		1
+#define DRIVER_MODE_DUAL_DIV		2
+
+/* Clock types */
+#define AD9545_CLK_OUT			0
+#define AD9545_CLK_PLL			1
+#define AD9545_CLK_NCO			2
+#define AD9545_CLK_AUX_TDC		3
+
+/* PLL addresses */
+#define AD9545_PLL0			0
+#define AD9545_PLL1			1
+
+/* Outputs addresses */
+#define AD9545_Q0A			0
+#define AD9545_Q0AA			1
+#define AD9545_Q0B			2
+#define AD9545_Q0BB			3
+#define AD9545_Q0C			4
+#define AD9545_Q0CC			5
+#define AD9545_Q1A			6
+#define AD9545_Q1AA			7
+#define AD9545_Q1B			8
+#define AD9545_Q1BB			9
+
+/* NCO addresses */
+#define AD9545_NCO0			0
+#define AD9545_NCO1			1
+
+/* TDC addresses */
+#define AD9545_CLK_AUX_TDC0		0
+#define AD9545_CLK_AUX_TDC1		1
+
+/* Ex:
+ * Output Q0C clock: <&ad9545_clock AD9545_CLK_OUT AD9545_Q0C>;
+ * PLL0 clock: <&ad9545_clock AD9545_CLK_PLL AD9545_PLL0>;
+ * NCO1 clock: <&ad9545_clock AD9545_CLK_NCO AD9545_NCO1>;
+ */
+
+#endif /* _DT_BINDINGS_CLOCK_AD9545_H_ */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 2/2] dt-bindings: clock: ad9545: Add documentation
  2021-06-14  7:07 ` [PATCH v2 2/2] dt-bindings: clock: ad9545: Add documentation alexandru.tachici
@ 2021-06-14 13:39   ` Rob Herring
  2021-06-15 22:50   ` Rob Herring
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Rob Herring @ 2021-06-14 13:39 UTC (permalink / raw)
  To: alexandru.tachici
  Cc: sboyd, linux-kernel, robh+dt, linux-clk, mturquette, devicetree,
	petre.minciunescu

On Mon, 14 Jun 2021 10:07:18 +0300, alexandru.tachici@analog.com wrote:
> From: Alexandru Tachici <alexandru.tachici@analog.com>
> 
> Add dt bindings for ad9545.
> 
> Signed-off-by: Alexandru Tachici <alexandru.tachici@analog.com>
> ---
>  .../devicetree/bindings/clock/clk-ad9545.yaml | 556 ++++++++++++++++++
>  include/dt-bindings/clock/ad9545.h            |  69 +++
>  2 files changed, 625 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/clk-ad9545.yaml
>  create mode 100644 include/dt-bindings/clock/ad9545.h
> 

My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:
./Documentation/devicetree/bindings/clock/clk-ad9545.yaml:115:10: [warning] wrong indentation: expected 8 but found 9 (indentation)
./Documentation/devicetree/bindings/clock/clk-ad9545.yaml:118:10: [warning] wrong indentation: expected 8 but found 9 (indentation)
./Documentation/devicetree/bindings/clock/clk-ad9545.yaml:153:10: [warning] wrong indentation: expected 8 but found 9 (indentation)
./Documentation/devicetree/bindings/clock/clk-ad9545.yaml:156:10: [warning] wrong indentation: expected 8 but found 9 (indentation)
./Documentation/devicetree/bindings/clock/clk-ad9545.yaml:280:10: [warning] wrong indentation: expected 8 but found 9 (indentation)
./Documentation/devicetree/bindings/clock/clk-ad9545.yaml:283:10: [warning] wrong indentation: expected 8 but found 9 (indentation)
./Documentation/devicetree/bindings/clock/clk-ad9545.yaml:298:14: [warning] wrong indentation: expected 12 but found 13 (indentation)
./Documentation/devicetree/bindings/clock/clk-ad9545.yaml:301:14: [warning] wrong indentation: expected 12 but found 13 (indentation)
./Documentation/devicetree/bindings/clock/clk-ad9545.yaml:389:10: [warning] wrong indentation: expected 8 but found 9 (indentation)
./Documentation/devicetree/bindings/clock/clk-ad9545.yaml:392:10: [warning] wrong indentation: expected 8 but found 9 (indentation)
./Documentation/devicetree/bindings/clock/clk-ad9545.yaml:435:10: [warning] wrong indentation: expected 8 but found 9 (indentation)
./Documentation/devicetree/bindings/clock/clk-ad9545.yaml:438:10: [warning] wrong indentation: expected 8 but found 9 (indentation)

dtschema/dtc warnings/errors:
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/clock/clk-ad9545.example.dt.yaml: ad9545@4A: 'clocks' is a dependency of 'assigned-clocks'
	From schema: /usr/local/lib/python3.8/dist-packages/dtschema/schemas/clock/clock.yaml
\ndoc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/patch/1491545

This check can fail if there are any dependencies. The base for a patch
series is generally the most recent rc1.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit.


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 2/2] dt-bindings: clock: ad9545: Add documentation
  2021-06-14  7:07 ` [PATCH v2 2/2] dt-bindings: clock: ad9545: Add documentation alexandru.tachici
  2021-06-14 13:39   ` Rob Herring
@ 2021-06-15 22:50   ` Rob Herring
  2021-06-16 18:53   ` kernel test robot
                     ` (3 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Rob Herring @ 2021-06-15 22:50 UTC (permalink / raw)
  To: alexandru.tachici
  Cc: linux-clk, linux-kernel, devicetree, sboyd, mturquette,
	petre.minciunescu

On Mon, Jun 14, 2021 at 10:07:18AM +0300, alexandru.tachici@analog.com wrote:
> From: Alexandru Tachici <alexandru.tachici@analog.com>
> 
> Add dt bindings for ad9545.

Kind of a lot of properties, not really sure what to do about that...

> 
> Signed-off-by: Alexandru Tachici <alexandru.tachici@analog.com>
> ---
>  .../devicetree/bindings/clock/clk-ad9545.yaml | 556 ++++++++++++++++++
>  include/dt-bindings/clock/ad9545.h            |  69 +++
>  2 files changed, 625 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/clk-ad9545.yaml
>  create mode 100644 include/dt-bindings/clock/ad9545.h
> 
> diff --git a/Documentation/devicetree/bindings/clock/clk-ad9545.yaml b/Documentation/devicetree/bindings/clock/clk-ad9545.yaml
> new file mode 100644
> index 000000000000..50553a88ab44
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/clk-ad9545.yaml
> @@ -0,0 +1,556 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/clock/clk-ad9545.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Analog Devices AD9545 Quad Input, 10-Output, Dual DPLL/IEEE 1588
> +
> +maintainers:
> +  - Alexandru Tachici <alexandru.tachici@analog.com>
> +
> +description: |
> +  Analog Devices AD9545 Quad Input, 10-Output, Dual DPLL/IEEE 1588,
> +  1 pps Synchronizer and Jitter Cleaner
> +  https://www.analog.com/media/en/technical-documentation/data-sheets/ADM1266.pdf
> +
> +properties:
> +  compatible:
> +    enum:
> +      - adi,ad9545
> +
> +  "#clock-cells":
> +    const: 2
> +
> +  reg:
> +    description: |

Don't need '|' if there's no formatting or anything that has to be 
escaped.

Same applies elsewhere.

> +      I2C address of the secondary device.
> +    minimum: 0
> +    maximum: 0xFF
> +
> +  avcc-supply:
> +    description: |
> +      Phandle to the Avcc power supply.
> +
> +  adi,freq-doubler:
> +    description: |
> +      The system clock PLL provides the user with the option of doubling the reference frequency.
> +    type: boolean
> +
> +  adi,ref-crystal:
> +    description: |
> +      At XOA,XOB there is a crystal connected that needs maintaining.
> +      Otherwise it is assumed that there is a TCXO or OCXO connected.
> +    type: boolean
> +
> +  adi,ref-frequency-hz:
> +    description: |
> +      Reference input frequency at XOA,XOB. This is used for the system clock.
> +
> +  clocks:
> +    items:
> +      - description: Ref A clock input
> +      - description: Ref AA clock input
> +      - description: Ref B clock input
> +      - description: Ref BB clock input
> +      - description: Ref M0 clock input
> +      - description: Ref M1 clock input
> +      - description: Ref M2 clock input
> +    maxItems: 4

Looks like 7 is the max...

> +
> +  assigned-clocks:
> +    description:
> +      Clocks are identified using two cells <&ad9545 clock_type clock_address>.
> +    minItems: 1
> +    maxItems: 14
> +
> +  assigned-clock-rates:
> +    minItems: 1
> +    maxItems: 14
> +
> +  assigned-clock-phases:
> +    minItems: 1
> +    maxItems: 14
> +
> +  clock-output-names:
> +    maxItems: 10
> +
> +  aux-dpll:
> +    description: |
> +      Auxiliary DPLL used for Closed-Loop method of system clock compensation.
> +    type: object
> +
> +    properties:
> +      adi,compensation-source:
> +        description: |
> +          System clock closed loop compensation source.
> +          Choose from Ref-A to Ref-BB [0-3] or aux TDCs [4-5].
> +        $ref: /schemas/types.yaml#/definitions/uint32
> +        enum: [0, 1, 2, 3, 4, 5]
> +
> +      adi,aux-dpll-bw-mhz:
> +        description: |
> +          Auxiliary DPLL bandwidth.
> +        minimum: 100
> +        maximum: 2000000
> +
> +      adi,rate-change-limit:
> +        description: |
> +          Error compensation rate change limiting expressed in ppb/s. Disabled if property is
> +          missing.
> +        $ref: /schemas/types.yaml#/definitions/uint32
> +        enum: [715, 1430, 2860, 5720, 11440, 22880, 45760]
> +
> +    required:
> +      - adi,compensation-source
> +      - adi,aux-dpll-bw-mhz
> +
> +  aux-tdc-clks:
> +    description: |
> +      Child nodes represent Mx pin reference clock inputs.
> +    type: object
> +
> +    properties:
> +      '#address-cells':
> +         const: 1
> +
> +      '#size-cells':
> +         const: 0
> +
> +    patternProperties:
> +      "^aux-tdc-clk@[0-3]$":
> +
> +        description: |
> +          Represents a Mx pin reference clock input.
> +        type: object
> +
> +        properties:
> +          reg:
> +            description: |
> +              Address of the Auxiliary TDC.
> +            maximum: 1

0-3 as the unit-address says or only 1? 

> +
> +          adi,pin-nr:
> +            description: |
> +              Pin number to be the source of this TDC.
> +            $ref: /schemas/types.yaml#/definitions/uint32
> +            minimum: 0
> +            maximum: 6
> +
> +        required:
> +          - reg
> +          - adi,pin-nr
> +
> +    additionalProperties: false
> +
> +  ref-input-clks:
> +    description: |
> +      Child nodes represent reference clock inputs.
> +    type: object
> +
> +    properties:
> +      '#address-cells':
> +         const: 1
> +
> +      '#size-cells':
> +         const: 0
> +
> +    patternProperties:
> +      "^ref-input-clk@[0-3]$":
> +        description: |
> +          Represents a reference clock input.
> +        type: object
> +
> +        properties:
> +          reg:
> +            description: |
> +              The reference input number. It can have up to 4 input clocks numbered from 0 to 3.
> +              (mapped: [refa, refaa, refb, refbb] -> [0, 1, 2, 3])
> +            maxItems: 1
> +
> +          adi,single-ended-mode:
> +            description: |
> +              Single-ended configuration mode.
> +            $ref: /schemas/types.yaml#/definitions/uint32
> +            enum: [0, 1, 2, 3]
> +
> +          adi,differential-mode:
> +            description: |
> +              Differential configuration mode.
> +            $ref: /schemas/types.yaml#/definitions/uint32
> +            enum: [0, 1, 2]
> +
> +          adi,r-divider-ratio:
> +            description: |
> +              Each reference input has a dedicated divider.
> +            $ref: /schemas/types.yaml#/definitions/uint32
> +            minimum: 1
> +            maximum: 1073741824
> +
> +          adi,ref-dtol-pbb:
> +            description: |
> +              REFx offset limit. Constitutes a fractional portion of the corresponding nominal period.
> +              The 24-bit number represents fractional units of parts per billion (ppb) up to a
> +              maximum of approximately 17 million ppb (1.7%).
> +            $ref: /schemas/types.yaml#/definitions/uint32
> +            minimum: 0
> +            maximum: 16777215
> +            default: 100000
> +
> +          adi,ref-monitor-hysteresis-pbb:
> +            description: |
> +              Basis points of the offset limit representing per ten thousand of REFx offset limit.
> +            $ref: /schemas/types.yaml#/definitions/uint32
> +            enum: [0, 3125, 6250, 12500, 25000, 50000, 75000, 87500]
> +            default: 12500
> +
> +          adi,ref-validation-timer-ms:
> +            description: |
> +              Time required for a reference to remain in tolerance condition before being
> +              available to be used.
> +            $ref: /schemas/types.yaml#/definitions/uint32
> +            minimum: 1
> +            maximum: 1048574
> +            default: 10
> +
> +          adi,freq-lock-threshold-ps:
> +            description: |
> +              Phase lock detector threshold (in picoseconds).
> +            $ref: /schemas/types.yaml#/definitions/uint32
> +            minimum: 1
> +            maximum: 16777215
> +
> +          adi,phase-lock-threshold-ps:
> +            description: |
> +              Profile 0 frequency lock threshold. Frequency lock detector threshold (in picoseconds).
> +            $ref: /schemas/types.yaml#/definitions/uint32
> +            minimum: 1
> +            maximum: 16777215
> +
> +          adi,phase-lock-fill-rate:
> +            description: |
> +              Parameter used by the DPLL Phase Lock Detector.
> +            $ref: /schemas/types.yaml#/definitions/uint32
> +            minimum: 1
> +            maximum: 255
> +            default: 10
> +
> +          adi,phase-lock-drain-rate:
> +            description: |
> +              Parameter used by the DPLL Phase Lock Detector.
> +            $ref: /schemas/types.yaml#/definitions/uint32
> +            minimum: 1
> +            maximum: 255
> +            default: 10
> +
> +          adi,freq-lock-fill-rate:
> +            description: |
> +              Parameter used by the DPLL Frequency Lock Detector.
> +            $ref: /schemas/types.yaml#/definitions/uint32
> +            minimum: 1
> +            maximum: 255
> +            default: 10
> +
> +          adi,freq-lock-drain-rate:
> +            description: |
> +              Parameter used by the DPLL Frequency Lock Detector.
> +            $ref: /schemas/types.yaml#/definitions/uint32
> +            minimum: 1
> +            maximum: 255
> +            default: 10
> +
> +        required:
> +          - reg
> +          - adi,r-divider-ratio
> +          - adi,ref-dtol-pbb
> +          - adi,ref-monitor-hysteresis-pbb
> +          - adi,ref-validation-timer-ms
> +          - adi,freq-lock-threshold-ps
> +          - adi,phase-lock-threshold-ps
> +
> +    additionalProperties: false
> +
> +  pll-clks:
> +    description: |
> +      Child nodes represent PLLs.
> +    type: object
> +
> +    properties:
> +      '#address-cells':
> +         const: 1
> +
> +      '#size-cells':
> +         const: 0
> +
> +    patternProperties:
> +      "^pll-clk@[0-1]$":
> +        description: |
> +          Represents a PLL.
> +        type: object
> +
> +        properties:
> +          reg:
> +            description: |
> +              PLL number. AD9545 has two PLLs.
> +            maxItems: 1
> +
> +          '#address-cells':
> +             const: 1
> +
> +          '#size-cells':
> +             const: 0
> +
> +          adi,fast-acq-trigger-mode:
> +            description: |
> +              If this is not specified Fast Acquisition will be used every time. See reg 0x2106
> +              for constraints on Fast Acquisition trigger.
> +            $ref: /schemas/types.yaml#/definitions/uint32
> +            minimum: 0
> +            maximum: 15
> +            default: 0
> +
> +        patternProperties:
> +          "^profile@[0-5]$":
> +            description: |
> +              Represents a DPLL profile. Each DPLL can have up to 6 specified sources
> +              wih priorities assigned.
> +            type: object
> +
> +            properties:
> +              reg:
> +                description: |
> +                  Profile number. A DPLL can have up to 6 translation profiles.
> +                maxItems: 1

Blank line

> +              adi,profile-priority:
> +                description: |
> +                  Profile selection priority. 0 is the highest, 31 is the lowest. For revertive
> +                  reference switching, ensure that priority difference is > 7.
> +                $ref: /schemas/types.yaml#/definitions/uint32
> +                minimum: 0
> +                maximum: 31
> +
> +              adi,pll-source:
> +                description: |
> +                  Each PLL can have 1 signal source. Choose from Ref-A to Ref-BB [0-3] or aux NCOs [4-5].
> +                $ref: /schemas/types.yaml#/definitions/uint32
> +                enum: [0, 1, 2, 3, 4, 5]
> +
> +              adi,pll-loop-bandwidth-uhz:
> +                description: |
> +                  PLL loop bandwidth in microhertz.
> +                $ref: /schemas/types.yaml#/definitions/uint32
> +                minimum: 1
> +                maximum: 1850000000
> +                default: 200000000
> +
> +              adi,fast-acq-excess-bw:
> +                description: |
> +                  Controls the DPLL loop bandwidth scaling factor while in fast acquisition mode.
> +                  0 means this feature is disabled.
> +                $ref: /schemas/types.yaml#/definitions/uint32
> +                enum: [0, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]
> +                default: 0
> +
> +              adi,fast-acq-timeout-ms:
> +                description: |
> +                  Fast acquisition timeout controls the maximum amount of time that DPLL waits to
> +                  achieve phase lock before reducing the loop bandwidth by a factor of two.
> +                $ref: /schemas/types.yaml#/definitions/uint32
> +                enum: [1, 10, 50, 100, 500, 1000, 10000, 50000]
> +                default: 1
> +
> +              adi,fast-acq-lock-settle-ms:
> +                description: |
> +                  Controls how long DPLL must wait after achieving phase lock before reducing
> +                  the loop bandwidth by a factor of 2.
> +                $ref: /schemas/types.yaml#/definitions/uint32
> +                enum: [1, 10, 50, 100, 500, 1000, 10000, 50000]
> +                default: 1
> +
> +            required:
> +              - reg
> +              - adi,pll-source
> +              - adi,pll-loop-bandwidth-uhz
> +
> +        additionalProperties: false
> +
> +        required:
> +          - reg
> +
> +    additionalProperties: false
> +
> +  aux-ncos:
> +    description: |
> +      Child nodes represent auxiliary Numerical Controlled Oscilators.
> +    type: object
> +
> +    properties:
> +      '#address-cells':
> +         const: 1
> +
> +      '#size-cells':
> +         const: 0
> +
> +    patternProperties:
> +      "^aux-nco-clk@[0-1]$":
> +        description: |
> +          Represents an auxiliary Numerical Controlled Oscilator. Generates timestamps that
> +          can be sent to the DPLL0 or DPLL1.
> +        type: object
> +
> +        properties:
> +          reg:
> +            description: |
> +              Auxiliary NCO address mapped: [NCO0, NCO1] -> [0, 1].
> +            maxItems: 1
> +
> +          adi,freq-lock-threshold-ps:
> +            description: |
> +              Phase lock detector threshold (in picoseconds).
> +            $ref: /schemas/types.yaml#/definitions/uint32
> +            minimum: 1
> +            maximum: 16777215
> +
> +          adi,phase-lock-threshold-ps:
> +            description: |
> +              Profile 0 frequency lock threshold. Frequency lock detector threshold (in picoseconds).
> +            $ref: /schemas/types.yaml#/definitions/uint32
> +            minimum: 1
> +            maximum: 16777215
> +
> +        required:
> +          - reg
> +          - adi,freq-lock-threshold-ps
> +          - adi,phase-lock-threshold-ps
> +
> +    additionalProperties: false
> +
> +  output-clks:
> +    description: |
> +      Child nodes represent clock outputs.
> +    type: object
> +
> +    properties:
> +      '#address-cells':
> +         const: 1
> +
> +      '#size-cells':
> +         const: 0
> +
> +    patternProperties:
> +      "^output-clk@([0-9]|1[0-3])$":
> +        description: |
> +          Represents a clock output.
> +        type: object
> +
> +        properties:
> +          reg:
> +            description: |
> +              The reference input number. It can have up to 10 output clocks mapped:
> +              (OUT0AP OUT0AN OUT0BP OUT0BN OUT0CP OUT0CN OUT1AP OUT1AN OUT1BP OUT1BN) ->
> +              (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

Looks like constraints (maximum: 9).

> +            maxItems: 1
> +
> +          adi,current-source:
> +            description: |
> +              If specified output is set as current source.
> +            type: boolean
> +
> +          adi,current-source-microamp:
> +            description: |
> +              The magnitude of the driver current.
> +            $ref: /schemas/types.yaml#/definitions/uint32
> +            enum: [7500, 12500, 15000]
> +
> +          adi,output-mode:
> +            description: |
> +              Output driver mode.
> +            $ref: /schemas/types.yaml#/definitions/uint32
> +            enum: [0, 1, 2]
> +
> +        required:
> +          - reg
> +          - adi,current-source-microamp
> +          - adi,output-mode
> +
> +    additionalProperties: false
> +
> +required:
> +  - compatible
> +  - reg
> +  - adi,ref-frequency-hz
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/ad9545.h>
> +
> +    i2c1 {

i2c {

> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +
> +        ad9545_clock: ad9545@4A {

clock-controller@4a

> +                compatible = "adi,ad9545";
> +                reg = <0x4A>;
> +
> +                adi,ref-crystal;
> +                adi,ref-frequency-hz = <52000000>;
> +
> +                #clock-cells = <2>;
> +                assigned-clocks = <&ad9545_clock AD9545_CLK_NCO AD9545_NCO0>,
> +                                  <&ad9545_clock AD9545_CLK_PLL AD9545_PLL1>,
> +                                  <&ad9545_clock AD9545_CLK_OUT AD9545_Q1A>,
> +                                  <&ad9545_clock AD9545_CLK_OUT AD9545_Q1B>;
> +                assigned-clock-rates = <10000>, <1875000000>, <156250000>, <156250000>;
> +                assigned-clock-phases = <0>, <0>, <0>, <180>;
> +
> +                aux-ncos {
> +                        #address-cells = <1>;
> +                        #size-cells = <0>;
> +
> +                        aux-nco-clk@AD9545_NCO0 {

Can't have defines in unit addresses. We generally don't have defines 
for 'reg' values.

> +                                reg = <AD9545_NCO0>;
> +                                adi,freq-lock-threshold-ps = <16000000>;
> +                                adi,phase-lock-threshold-ps = <16000000>;
> +                        };
> +                };
> +
> +                pll-clks {
> +                        #address-cells = <1>;
> +                        #size-cells = <0>;
> +
> +                        ad9545_apll1: pll-clk@AD9545_PLL1 {
> +                                reg = <AD9545_PLL1>;
> +
> +                                #address-cells = <1>;
> +                                #size-cells = <0>;
> +
> +                                profile@0 {
> +                                       reg = <0>;
> +                                       adi,pll-source = <4>;
> +                                       adi,profile-priority = <0>;
> +                                       adi,pll-loop-bandwidth-uhz = <200000000>;
> +                                };
> +                        };
> +                };
> +
> +                output-clks {
> +                        #address-cells = <1>;
> +                        #size-cells = <0>;
> +
> +                        output-clk@AD9545_Q1A {
> +                                reg = <AD9545_Q1A>;
> +                                adi,output-mode = <DRIVER_MODE_DUAL_DIV>;
> +                                adi,current-source-microamp = <15000>;
> +                        };
> +
> +                        output-clk@AD9545_Q1B {
> +                                reg = <AD9545_Q1B>;
> +                                adi,output-mode = <DRIVER_MODE_DUAL_DIV>;
> +                                adi,current-source-microamp = <15000>;
> +                        };
> +                };
> +        };
> +    };
> +...
> diff --git a/include/dt-bindings/clock/ad9545.h b/include/dt-bindings/clock/ad9545.h
> new file mode 100644
> index 000000000000..857d50e5715b
> --- /dev/null
> +++ b/include/dt-bindings/clock/ad9545.h
> @@ -0,0 +1,69 @@
> +/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
> +/*
> + * AD9545 Network Clock Generator/Synchronizer
> + *
> + * Copyright 2020 Analog Devices Inc.
> + */
> +
> +#ifndef _DT_BINDINGS_CLOCK_AD9545_H_
> +#define _DT_BINDINGS_CLOCK_AD9545_H_
> +
> +/* Input Driver Mode
> + * Use for adi,single-ended-mode:
> + */
> +#define DRIVER_MODE_AC_COUPLED_IF	0
> +#define DRIVER_MODE_DC_COUPLED_1V2	1
> +#define DRIVER_MODE_DC_COUPLED_1V8	2
> +#define DRIVER_MODE_IN_PULL_UP		3
> +
> +/* Input Driver Mode
> + * Use for adi,differential-mode:
> + */
> +#define DRIVER_MODE_AC_COUPLED		0
> +#define DRIVER_MODE_DC_COUPLED		1
> +#define DRIVER_MODE_DC_COUPLED_LVDS	2
> +
> +/* Output Driver Mode
> + * Use for adi,output-mode:
> + */
> +#define DRIVER_MODE_SINGLE_DIV_DIF	0
> +#define DRIVER_MODE_SINGLE_DIV		1
> +#define DRIVER_MODE_DUAL_DIV		2
> +
> +/* Clock types */
> +#define AD9545_CLK_OUT			0
> +#define AD9545_CLK_PLL			1
> +#define AD9545_CLK_NCO			2
> +#define AD9545_CLK_AUX_TDC		3
> +
> +/* PLL addresses */
> +#define AD9545_PLL0			0
> +#define AD9545_PLL1			1
> +
> +/* Outputs addresses */
> +#define AD9545_Q0A			0
> +#define AD9545_Q0AA			1
> +#define AD9545_Q0B			2
> +#define AD9545_Q0BB			3
> +#define AD9545_Q0C			4
> +#define AD9545_Q0CC			5
> +#define AD9545_Q1A			6
> +#define AD9545_Q1AA			7
> +#define AD9545_Q1B			8
> +#define AD9545_Q1BB			9
> +
> +/* NCO addresses */
> +#define AD9545_NCO0			0
> +#define AD9545_NCO1			1
> +
> +/* TDC addresses */
> +#define AD9545_CLK_AUX_TDC0		0
> +#define AD9545_CLK_AUX_TDC1		1
> +
> +/* Ex:
> + * Output Q0C clock: <&ad9545_clock AD9545_CLK_OUT AD9545_Q0C>;
> + * PLL0 clock: <&ad9545_clock AD9545_CLK_PLL AD9545_PLL0>;
> + * NCO1 clock: <&ad9545_clock AD9545_CLK_NCO AD9545_NCO1>;
> + */
> +
> +#endif /* _DT_BINDINGS_CLOCK_AD9545_H_ */
> -- 
> 2.25.1

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 2/2] dt-bindings: clock: ad9545: Add documentation
  2021-06-14  7:07 ` [PATCH v2 2/2] dt-bindings: clock: ad9545: Add documentation alexandru.tachici
  2021-06-14 13:39   ` Rob Herring
  2021-06-15 22:50   ` Rob Herring
@ 2021-06-16 18:53   ` kernel test robot
  2021-06-17  7:55   ` kernel test robot
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: kernel test robot @ 2021-06-16 18:53 UTC (permalink / raw)
  To: alexandru.tachici, linux-clk, linux-kernel, devicetree
  Cc: kbuild-all, robh+dt, sboyd, mturquette, petre.minciunescu,
	Alexandru Tachici

[-- Attachment #1: Type: text/plain, Size: 3520 bytes --]

Hi,

I love your patch! Perhaps something to improve:

[auto build test WARNING on clk/clk-next]
[also build test WARNING on robh/for-next linux/master linus/master v5.13-rc6 next-20210616]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/alexandru-tachici-analog-com/clk-ad9545-Add-support/20210616-153412
base:   https://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git clk-next
config: m68k-allmodconfig (attached as .config)
compiler: m68k-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/b46755cf562ff8a1a9841a4560e344099f3f054e
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review alexandru-tachici-analog-com/clk-ad9545-Add-support/20210616-153412
        git checkout b46755cf562ff8a1a9841a4560e344099f3f054e
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=m68k 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/clk/adi/clk-ad9545.c:2402:5: warning: no previous prototype for 'ad9545_probe' [-Wmissing-prototypes]
    2402 | int ad9545_probe(struct device *dev, struct regmap *regmap)
         |     ^~~~~~~~~~~~


vim +/ad9545_probe +2402 drivers/clk/adi/clk-ad9545.c

f88d17c990b731 Alexandru Tachici 2021-06-14  2401  
f88d17c990b731 Alexandru Tachici 2021-06-14 @2402  int ad9545_probe(struct device *dev, struct regmap *regmap)
f88d17c990b731 Alexandru Tachici 2021-06-14  2403  {
f88d17c990b731 Alexandru Tachici 2021-06-14  2404  	struct ad9545_state *st;
f88d17c990b731 Alexandru Tachici 2021-06-14  2405  	int ret;
f88d17c990b731 Alexandru Tachici 2021-06-14  2406  
f88d17c990b731 Alexandru Tachici 2021-06-14  2407  	st = devm_kzalloc(dev, sizeof(struct ad9545_state), GFP_KERNEL);
f88d17c990b731 Alexandru Tachici 2021-06-14  2408  	if (!st)
f88d17c990b731 Alexandru Tachici 2021-06-14  2409  		return -ENOMEM;
f88d17c990b731 Alexandru Tachici 2021-06-14  2410  
f88d17c990b731 Alexandru Tachici 2021-06-14  2411  	st->dev = dev;
f88d17c990b731 Alexandru Tachici 2021-06-14  2412  	st->regmap = regmap;
f88d17c990b731 Alexandru Tachici 2021-06-14  2413  
f88d17c990b731 Alexandru Tachici 2021-06-14  2414  	ret = ad9545_check_id(st);
f88d17c990b731 Alexandru Tachici 2021-06-14  2415  	if (ret < 0)
f88d17c990b731 Alexandru Tachici 2021-06-14  2416  		return ret;
f88d17c990b731 Alexandru Tachici 2021-06-14  2417  
f88d17c990b731 Alexandru Tachici 2021-06-14  2418  	ret = ad9545_parse_dt(st);
f88d17c990b731 Alexandru Tachici 2021-06-14  2419  	if (ret < 0)
f88d17c990b731 Alexandru Tachici 2021-06-14  2420  		return ret;
f88d17c990b731 Alexandru Tachici 2021-06-14  2421  
f88d17c990b731 Alexandru Tachici 2021-06-14  2422  	return ad9545_setup(st);
f88d17c990b731 Alexandru Tachici 2021-06-14  2423  }
f88d17c990b731 Alexandru Tachici 2021-06-14  2424  EXPORT_SYMBOL_GPL(ad9545_probe);
f88d17c990b731 Alexandru Tachici 2021-06-14  2425  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 59091 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 2/2] dt-bindings: clock: ad9545: Add documentation
  2021-06-14  7:07 ` [PATCH v2 2/2] dt-bindings: clock: ad9545: Add documentation alexandru.tachici
                     ` (2 preceding siblings ...)
  2021-06-16 18:53   ` kernel test robot
@ 2021-06-17  7:55   ` kernel test robot
  2021-06-18  4:17   ` kernel test robot
  2021-06-22  7:02   ` kernel test robot
  5 siblings, 0 replies; 9+ messages in thread
From: kernel test robot @ 2021-06-17  7:55 UTC (permalink / raw)
  To: alexandru.tachici, linux-clk, linux-kernel, devicetree
  Cc: kbuild-all, robh+dt, sboyd, mturquette, petre.minciunescu,
	Alexandru Tachici

[-- Attachment #1: Type: text/plain, Size: 7962 bytes --]

Hi,

I love your patch! Perhaps something to improve:

[auto build test WARNING on clk/clk-next]
[also build test WARNING on robh/for-next linux/master linus/master v5.13-rc6 next-20210616]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/alexandru-tachici-analog-com/clk-ad9545-Add-support/20210616-153412
base:   https://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git clk-next
config: i386-randconfig-s032-20210617 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.3-341-g8af24329-dirty
        # https://github.com/0day-ci/linux/commit/b46755cf562ff8a1a9841a4560e344099f3f054e
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review alexandru-tachici-analog-com/clk-ad9545-Add-support/20210616-153412
        git checkout b46755cf562ff8a1a9841a4560e344099f3f054e
        # save the attached .config to linux build tree
        make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' W=1 ARCH=i386 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>


sparse warnings: (new ones prefixed by >>)
>> drivers/clk/adi/clk-ad9545.c:1114:43: sparse: sparse: cast from restricted __le32
>> drivers/clk/adi/clk-ad9545.c:1114:43: sparse: sparse: restricted __le32 degrades to integer
>> drivers/clk/adi/clk-ad9545.c:1407:24: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le32 [addressable] [assigned] [usertype] regval @@     got unsigned int freq_lock_fill_rate @@
   drivers/clk/adi/clk-ad9545.c:1407:24: sparse:     expected restricted __le32 [addressable] [assigned] [usertype] regval
   drivers/clk/adi/clk-ad9545.c:1407:24: sparse:     got unsigned int freq_lock_fill_rate
>> drivers/clk/adi/clk-ad9545.c:1409:88: sparse: sparse: incorrect type in argument 3 (different base types) @@     expected unsigned int val @@     got restricted __le32 [addressable] [assigned] [usertype] regval @@
   drivers/clk/adi/clk-ad9545.c:1409:88: sparse:     expected unsigned int val
   drivers/clk/adi/clk-ad9545.c:1409:88: sparse:     got restricted __le32 [addressable] [assigned] [usertype] regval
>> drivers/clk/adi/clk-ad9545.c:1414:24: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le32 [addressable] [assigned] [usertype] regval @@     got unsigned int freq_lock_drain_rate @@
   drivers/clk/adi/clk-ad9545.c:1414:24: sparse:     expected restricted __le32 [addressable] [assigned] [usertype] regval
   drivers/clk/adi/clk-ad9545.c:1414:24: sparse:     got unsigned int freq_lock_drain_rate
   drivers/clk/adi/clk-ad9545.c:1416:89: sparse: sparse: incorrect type in argument 3 (different base types) @@     expected unsigned int val @@     got restricted __le32 [addressable] [assigned] [usertype] regval @@
   drivers/clk/adi/clk-ad9545.c:1416:89: sparse:     expected unsigned int val
   drivers/clk/adi/clk-ad9545.c:1416:89: sparse:     got restricted __le32 [addressable] [assigned] [usertype] regval
>> drivers/clk/adi/clk-ad9545.c:1421:24: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le32 [addressable] [assigned] [usertype] regval @@     got unsigned int phase_lock_fill_rate @@
   drivers/clk/adi/clk-ad9545.c:1421:24: sparse:     expected restricted __le32 [addressable] [assigned] [usertype] regval
   drivers/clk/adi/clk-ad9545.c:1421:24: sparse:     got unsigned int phase_lock_fill_rate
   drivers/clk/adi/clk-ad9545.c:1423:89: sparse: sparse: incorrect type in argument 3 (different base types) @@     expected unsigned int val @@     got restricted __le32 [addressable] [assigned] [usertype] regval @@
   drivers/clk/adi/clk-ad9545.c:1423:89: sparse:     expected unsigned int val
   drivers/clk/adi/clk-ad9545.c:1423:89: sparse:     got restricted __le32 [addressable] [assigned] [usertype] regval
>> drivers/clk/adi/clk-ad9545.c:1428:24: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le32 [addressable] [assigned] [usertype] regval @@     got unsigned int phase_lock_drain_rate @@
   drivers/clk/adi/clk-ad9545.c:1428:24: sparse:     expected restricted __le32 [addressable] [assigned] [usertype] regval
   drivers/clk/adi/clk-ad9545.c:1428:24: sparse:     got unsigned int phase_lock_drain_rate
   drivers/clk/adi/clk-ad9545.c:1430:90: sparse: sparse: incorrect type in argument 3 (different base types) @@     expected unsigned int val @@     got restricted __le32 [addressable] [assigned] [usertype] regval @@
   drivers/clk/adi/clk-ad9545.c:1430:90: sparse:     expected unsigned int val
   drivers/clk/adi/clk-ad9545.c:1430:90: sparse:     got restricted __le32 [addressable] [assigned] [usertype] regval

vim +1114 drivers/clk/adi/clk-ad9545.c

f88d17c990b731 Alexandru Tachici 2021-06-14  1089  
f88d17c990b731 Alexandru Tachici 2021-06-14  1090  static int ad9545_out_clk_get_phase(struct clk_hw *hw)
f88d17c990b731 Alexandru Tachici 2021-06-14  1091  {
f88d17c990b731 Alexandru Tachici 2021-06-14  1092  	struct ad9545_out_clk *clk = to_out_clk(hw);
f88d17c990b731 Alexandru Tachici 2021-06-14  1093  	u64 input_edges_nr;
f88d17c990b731 Alexandru Tachici 2021-06-14  1094  	u64 phase_code;
f88d17c990b731 Alexandru Tachici 2021-06-14  1095  	__le32 regval;
f88d17c990b731 Alexandru Tachici 2021-06-14  1096  	u32 phase_conf;
f88d17c990b731 Alexandru Tachici 2021-06-14  1097  	u32 qdiv;
f88d17c990b731 Alexandru Tachici 2021-06-14  1098  	int ret;
f88d17c990b731 Alexandru Tachici 2021-06-14  1099  
f88d17c990b731 Alexandru Tachici 2021-06-14  1100  	ret = ad9545_get_q_div(clk->st, clk->address, &qdiv);
f88d17c990b731 Alexandru Tachici 2021-06-14  1101  	if (ret < 0)
f88d17c990b731 Alexandru Tachici 2021-06-14  1102  		return ret;
f88d17c990b731 Alexandru Tachici 2021-06-14  1103  
f88d17c990b731 Alexandru Tachici 2021-06-14  1104  	ret = regmap_read(clk->st->regmap, AD9545_QX_PHASE_CONF(clk->address), &phase_conf);
f88d17c990b731 Alexandru Tachici 2021-06-14  1105  	if (ret < 0)
f88d17c990b731 Alexandru Tachici 2021-06-14  1106  		return ret;
f88d17c990b731 Alexandru Tachici 2021-06-14  1107  
f88d17c990b731 Alexandru Tachici 2021-06-14  1108  	ret = regmap_bulk_read(clk->st->regmap, AD9545_QX_PHASE(clk->address), &regval, 4);
f88d17c990b731 Alexandru Tachici 2021-06-14  1109  	if (ret < 0)
f88d17c990b731 Alexandru Tachici 2021-06-14  1110  		return ret;
f88d17c990b731 Alexandru Tachici 2021-06-14  1111  
f88d17c990b731 Alexandru Tachici 2021-06-14  1112  	/* Qxy phase bitfield is 33 bits long, with last bit in PHASE_CONF reg */
f88d17c990b731 Alexandru Tachici 2021-06-14  1113  	phase_code = !!(phase_conf & AD9545_QX_PHASE_32_MSK);
f88d17c990b731 Alexandru Tachici 2021-06-14 @1114  	phase_code = (phase_code >> 32) + cpu_to_le32(regval);
f88d17c990b731 Alexandru Tachici 2021-06-14  1115  
f88d17c990b731 Alexandru Tachici 2021-06-14  1116  	input_edges_nr = 2 * qdiv + !!(phase_conf & AD9545_QX_HALF_DIV_MSK);
f88d17c990b731 Alexandru Tachici 2021-06-14  1117  
f88d17c990b731 Alexandru Tachici 2021-06-14  1118  	/*
f88d17c990b731 Alexandru Tachici 2021-06-14  1119  	 * phase = 360 * (Qxy Phase / E) where:
f88d17c990b731 Alexandru Tachici 2021-06-14  1120  	 * E is the total number of input edges per output period of the Q-divider.
f88d17c990b731 Alexandru Tachici 2021-06-14  1121  	 */
f88d17c990b731 Alexandru Tachici 2021-06-14  1122  	return div64_u64(phase_code * 360, input_edges_nr);
f88d17c990b731 Alexandru Tachici 2021-06-14  1123  }
f88d17c990b731 Alexandru Tachici 2021-06-14  1124  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 35662 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 2/2] dt-bindings: clock: ad9545: Add documentation
  2021-06-14  7:07 ` [PATCH v2 2/2] dt-bindings: clock: ad9545: Add documentation alexandru.tachici
                     ` (3 preceding siblings ...)
  2021-06-17  7:55   ` kernel test robot
@ 2021-06-18  4:17   ` kernel test robot
  2021-06-22  7:02   ` kernel test robot
  5 siblings, 0 replies; 9+ messages in thread
From: kernel test robot @ 2021-06-18  4:17 UTC (permalink / raw)
  To: alexandru.tachici, linux-clk, linux-kernel, devicetree
  Cc: kbuild-all, robh+dt, sboyd, mturquette, petre.minciunescu,
	Alexandru Tachici

[-- Attachment #1: Type: text/plain, Size: 8910 bytes --]

Hi,

I love your patch! Perhaps something to improve:

[auto build test WARNING on clk/clk-next]
[also build test WARNING on robh/for-next linux/master linus/master v5.13-rc6 next-20210617]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/alexandru-tachici-analog-com/clk-ad9545-Add-support/20210616-153412
base:   https://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git clk-next
config: h8300-randconfig-s031-20210618 (attached as .config)
compiler: h8300-linux-gcc (GCC) 9.3.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # apt-get install sparse
        # sparse version: v0.6.3-341-g8af24329-dirty
        # https://github.com/0day-ci/linux/commit/b46755cf562ff8a1a9841a4560e344099f3f054e
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review alexandru-tachici-analog-com/clk-ad9545-Add-support/20210616-153412
        git checkout b46755cf562ff8a1a9841a4560e344099f3f054e
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' W=1 ARCH=h8300 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>


sparse warnings: (new ones prefixed by >>)
   drivers/clk/adi/clk-ad9545.c:1114:43: sparse: sparse: cast from restricted __le32
>> drivers/clk/adi/clk-ad9545.c:1114:43: sparse: sparse: incorrect type in argument 1 (different base types) @@     expected unsigned int [usertype] val @@     got restricted __le32 [addressable] [usertype] regval @@
   drivers/clk/adi/clk-ad9545.c:1114:43: sparse:     expected unsigned int [usertype] val
   drivers/clk/adi/clk-ad9545.c:1114:43: sparse:     got restricted __le32 [addressable] [usertype] regval
   drivers/clk/adi/clk-ad9545.c:1114:43: sparse: sparse: cast from restricted __le32
   drivers/clk/adi/clk-ad9545.c:1114:43: sparse: sparse: cast from restricted __le32
   drivers/clk/adi/clk-ad9545.c:1114:43: sparse: sparse: cast from restricted __le32
   drivers/clk/adi/clk-ad9545.c:1114:43: sparse: sparse: cast from restricted __le32
   drivers/clk/adi/clk-ad9545.c:1114:43: sparse: sparse: restricted __le32 degrades to integer
   drivers/clk/adi/clk-ad9545.c:1407:24: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le32 [addressable] [assigned] [usertype] regval @@     got unsigned int freq_lock_fill_rate @@
   drivers/clk/adi/clk-ad9545.c:1407:24: sparse:     expected restricted __le32 [addressable] [assigned] [usertype] regval
   drivers/clk/adi/clk-ad9545.c:1407:24: sparse:     got unsigned int freq_lock_fill_rate
   drivers/clk/adi/clk-ad9545.c:1409:88: sparse: sparse: incorrect type in argument 3 (different base types) @@     expected unsigned int val @@     got restricted __le32 [addressable] [assigned] [usertype] regval @@
   drivers/clk/adi/clk-ad9545.c:1409:88: sparse:     expected unsigned int val
   drivers/clk/adi/clk-ad9545.c:1409:88: sparse:     got restricted __le32 [addressable] [assigned] [usertype] regval
   drivers/clk/adi/clk-ad9545.c:1414:24: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le32 [addressable] [assigned] [usertype] regval @@     got unsigned int freq_lock_drain_rate @@
   drivers/clk/adi/clk-ad9545.c:1414:24: sparse:     expected restricted __le32 [addressable] [assigned] [usertype] regval
   drivers/clk/adi/clk-ad9545.c:1414:24: sparse:     got unsigned int freq_lock_drain_rate
   drivers/clk/adi/clk-ad9545.c:1416:89: sparse: sparse: incorrect type in argument 3 (different base types) @@     expected unsigned int val @@     got restricted __le32 [addressable] [assigned] [usertype] regval @@
   drivers/clk/adi/clk-ad9545.c:1416:89: sparse:     expected unsigned int val
   drivers/clk/adi/clk-ad9545.c:1416:89: sparse:     got restricted __le32 [addressable] [assigned] [usertype] regval
   drivers/clk/adi/clk-ad9545.c:1421:24: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le32 [addressable] [assigned] [usertype] regval @@     got unsigned int phase_lock_fill_rate @@
   drivers/clk/adi/clk-ad9545.c:1421:24: sparse:     expected restricted __le32 [addressable] [assigned] [usertype] regval
   drivers/clk/adi/clk-ad9545.c:1421:24: sparse:     got unsigned int phase_lock_fill_rate
   drivers/clk/adi/clk-ad9545.c:1423:89: sparse: sparse: incorrect type in argument 3 (different base types) @@     expected unsigned int val @@     got restricted __le32 [addressable] [assigned] [usertype] regval @@
   drivers/clk/adi/clk-ad9545.c:1423:89: sparse:     expected unsigned int val
   drivers/clk/adi/clk-ad9545.c:1423:89: sparse:     got restricted __le32 [addressable] [assigned] [usertype] regval
   drivers/clk/adi/clk-ad9545.c:1428:24: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le32 [addressable] [assigned] [usertype] regval @@     got unsigned int phase_lock_drain_rate @@
   drivers/clk/adi/clk-ad9545.c:1428:24: sparse:     expected restricted __le32 [addressable] [assigned] [usertype] regval
   drivers/clk/adi/clk-ad9545.c:1428:24: sparse:     got unsigned int phase_lock_drain_rate
   drivers/clk/adi/clk-ad9545.c:1430:90: sparse: sparse: incorrect type in argument 3 (different base types) @@     expected unsigned int val @@     got restricted __le32 [addressable] [assigned] [usertype] regval @@
   drivers/clk/adi/clk-ad9545.c:1430:90: sparse:     expected unsigned int val
   drivers/clk/adi/clk-ad9545.c:1430:90: sparse:     got restricted __le32 [addressable] [assigned] [usertype] regval

vim +1114 drivers/clk/adi/clk-ad9545.c

f88d17c990b731 Alexandru Tachici 2021-06-14  1089  
f88d17c990b731 Alexandru Tachici 2021-06-14  1090  static int ad9545_out_clk_get_phase(struct clk_hw *hw)
f88d17c990b731 Alexandru Tachici 2021-06-14  1091  {
f88d17c990b731 Alexandru Tachici 2021-06-14  1092  	struct ad9545_out_clk *clk = to_out_clk(hw);
f88d17c990b731 Alexandru Tachici 2021-06-14  1093  	u64 input_edges_nr;
f88d17c990b731 Alexandru Tachici 2021-06-14  1094  	u64 phase_code;
f88d17c990b731 Alexandru Tachici 2021-06-14  1095  	__le32 regval;
f88d17c990b731 Alexandru Tachici 2021-06-14  1096  	u32 phase_conf;
f88d17c990b731 Alexandru Tachici 2021-06-14  1097  	u32 qdiv;
f88d17c990b731 Alexandru Tachici 2021-06-14  1098  	int ret;
f88d17c990b731 Alexandru Tachici 2021-06-14  1099  
f88d17c990b731 Alexandru Tachici 2021-06-14  1100  	ret = ad9545_get_q_div(clk->st, clk->address, &qdiv);
f88d17c990b731 Alexandru Tachici 2021-06-14  1101  	if (ret < 0)
f88d17c990b731 Alexandru Tachici 2021-06-14  1102  		return ret;
f88d17c990b731 Alexandru Tachici 2021-06-14  1103  
f88d17c990b731 Alexandru Tachici 2021-06-14  1104  	ret = regmap_read(clk->st->regmap, AD9545_QX_PHASE_CONF(clk->address), &phase_conf);
f88d17c990b731 Alexandru Tachici 2021-06-14  1105  	if (ret < 0)
f88d17c990b731 Alexandru Tachici 2021-06-14  1106  		return ret;
f88d17c990b731 Alexandru Tachici 2021-06-14  1107  
f88d17c990b731 Alexandru Tachici 2021-06-14  1108  	ret = regmap_bulk_read(clk->st->regmap, AD9545_QX_PHASE(clk->address), &regval, 4);
f88d17c990b731 Alexandru Tachici 2021-06-14  1109  	if (ret < 0)
f88d17c990b731 Alexandru Tachici 2021-06-14  1110  		return ret;
f88d17c990b731 Alexandru Tachici 2021-06-14  1111  
f88d17c990b731 Alexandru Tachici 2021-06-14  1112  	/* Qxy phase bitfield is 33 bits long, with last bit in PHASE_CONF reg */
f88d17c990b731 Alexandru Tachici 2021-06-14  1113  	phase_code = !!(phase_conf & AD9545_QX_PHASE_32_MSK);
f88d17c990b731 Alexandru Tachici 2021-06-14 @1114  	phase_code = (phase_code >> 32) + cpu_to_le32(regval);
f88d17c990b731 Alexandru Tachici 2021-06-14  1115  
f88d17c990b731 Alexandru Tachici 2021-06-14  1116  	input_edges_nr = 2 * qdiv + !!(phase_conf & AD9545_QX_HALF_DIV_MSK);
f88d17c990b731 Alexandru Tachici 2021-06-14  1117  
f88d17c990b731 Alexandru Tachici 2021-06-14  1118  	/*
f88d17c990b731 Alexandru Tachici 2021-06-14  1119  	 * phase = 360 * (Qxy Phase / E) where:
f88d17c990b731 Alexandru Tachici 2021-06-14  1120  	 * E is the total number of input edges per output period of the Q-divider.
f88d17c990b731 Alexandru Tachici 2021-06-14  1121  	 */
f88d17c990b731 Alexandru Tachici 2021-06-14  1122  	return div64_u64(phase_code * 360, input_edges_nr);
f88d17c990b731 Alexandru Tachici 2021-06-14  1123  }
f88d17c990b731 Alexandru Tachici 2021-06-14  1124  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 24223 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 2/2] dt-bindings: clock: ad9545: Add documentation
  2021-06-14  7:07 ` [PATCH v2 2/2] dt-bindings: clock: ad9545: Add documentation alexandru.tachici
                     ` (4 preceding siblings ...)
  2021-06-18  4:17   ` kernel test robot
@ 2021-06-22  7:02   ` kernel test robot
  5 siblings, 0 replies; 9+ messages in thread
From: kernel test robot @ 2021-06-22  7:02 UTC (permalink / raw)
  To: alexandru.tachici, linux-clk, linux-kernel, devicetree
  Cc: kbuild-all, clang-built-linux, robh+dt, sboyd, mturquette,
	petre.minciunescu, Alexandru Tachici

[-- Attachment #1: Type: text/plain, Size: 3944 bytes --]

Hi,

I love your patch! Perhaps something to improve:

[auto build test WARNING on clk/clk-next]
[also build test WARNING on robh/for-next linux/master linus/master v5.13-rc7 next-20210621]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/alexandru-tachici-analog-com/clk-ad9545-Add-support/20210616-153412
base:   https://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git clk-next
config: x86_64-randconfig-r005-20210622 (attached as .config)
compiler: clang version 13.0.0 (https://github.com/llvm/llvm-project b3634d3e88b7f26534a5057bff182b7dced584fc)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install x86_64 cross compiling tool for clang build
        # apt-get install binutils-x86-64-linux-gnu
        # https://github.com/0day-ci/linux/commit/b46755cf562ff8a1a9841a4560e344099f3f054e
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review alexandru-tachici-analog-com/clk-ad9545-Add-support/20210616-153412
        git checkout b46755cf562ff8a1a9841a4560e344099f3f054e
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/clk/adi/clk-ad9545.c:2402:5: warning: no previous prototype for function 'ad9545_probe' [-Wmissing-prototypes]
   int ad9545_probe(struct device *dev, struct regmap *regmap)
       ^
   drivers/clk/adi/clk-ad9545.c:2402:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   int ad9545_probe(struct device *dev, struct regmap *regmap)
   ^
   static 
   1 warning generated.


vim +/ad9545_probe +2402 drivers/clk/adi/clk-ad9545.c

f88d17c990b731 Alexandru Tachici 2021-06-14  2401  
f88d17c990b731 Alexandru Tachici 2021-06-14 @2402  int ad9545_probe(struct device *dev, struct regmap *regmap)
f88d17c990b731 Alexandru Tachici 2021-06-14  2403  {
f88d17c990b731 Alexandru Tachici 2021-06-14  2404  	struct ad9545_state *st;
f88d17c990b731 Alexandru Tachici 2021-06-14  2405  	int ret;
f88d17c990b731 Alexandru Tachici 2021-06-14  2406  
f88d17c990b731 Alexandru Tachici 2021-06-14  2407  	st = devm_kzalloc(dev, sizeof(struct ad9545_state), GFP_KERNEL);
f88d17c990b731 Alexandru Tachici 2021-06-14  2408  	if (!st)
f88d17c990b731 Alexandru Tachici 2021-06-14  2409  		return -ENOMEM;
f88d17c990b731 Alexandru Tachici 2021-06-14  2410  
f88d17c990b731 Alexandru Tachici 2021-06-14  2411  	st->dev = dev;
f88d17c990b731 Alexandru Tachici 2021-06-14  2412  	st->regmap = regmap;
f88d17c990b731 Alexandru Tachici 2021-06-14  2413  
f88d17c990b731 Alexandru Tachici 2021-06-14  2414  	ret = ad9545_check_id(st);
f88d17c990b731 Alexandru Tachici 2021-06-14  2415  	if (ret < 0)
f88d17c990b731 Alexandru Tachici 2021-06-14  2416  		return ret;
f88d17c990b731 Alexandru Tachici 2021-06-14  2417  
f88d17c990b731 Alexandru Tachici 2021-06-14  2418  	ret = ad9545_parse_dt(st);
f88d17c990b731 Alexandru Tachici 2021-06-14  2419  	if (ret < 0)
f88d17c990b731 Alexandru Tachici 2021-06-14  2420  		return ret;
f88d17c990b731 Alexandru Tachici 2021-06-14  2421  
f88d17c990b731 Alexandru Tachici 2021-06-14  2422  	return ad9545_setup(st);
f88d17c990b731 Alexandru Tachici 2021-06-14  2423  }
f88d17c990b731 Alexandru Tachici 2021-06-14  2424  EXPORT_SYMBOL_GPL(ad9545_probe);
f88d17c990b731 Alexandru Tachici 2021-06-14  2425  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 37666 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2021-06-22  7:03 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-14  7:07 [PATCH v2 0/2] clk: ad9545: Add support alexandru.tachici
2021-06-14  7:07 ` [PATCH v2 1/2] " alexandru.tachici
2021-06-14  7:07 ` [PATCH v2 2/2] dt-bindings: clock: ad9545: Add documentation alexandru.tachici
2021-06-14 13:39   ` Rob Herring
2021-06-15 22:50   ` Rob Herring
2021-06-16 18:53   ` kernel test robot
2021-06-17  7:55   ` kernel test robot
2021-06-18  4:17   ` kernel test robot
2021-06-22  7:02   ` kernel test robot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).