linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 0/7] clk: axi-clk-gen: misc updates to the driver
@ 2020-09-29 14:44 Alexandru Ardelean
  2020-09-29 14:44 ` [PATCH v4 1/7] clk: axi-clkgen: Add support for fractional dividers Alexandru Ardelean
                   ` (14 more replies)
  0 siblings, 15 replies; 22+ messages in thread
From: Alexandru Ardelean @ 2020-09-29 14:44 UTC (permalink / raw)
  To: linux-clk, linux-fpga, linux-kernel
  Cc: mturquette, sboyd, mdf, ardeleanalex, Alexandru Ardelean

These patches synchronize the driver with the current state in the
Analog Devices Linux tree:
  https://github.com/analogdevicesinc/linux/

They have been in the tree for about 2-3, so they did receive some
testing.

Highlights are:
* Add support for fractional dividers (Lars-Peter Clausen)
* Enable support for ZynqMP (UltraScale) (Dragos Bogdan)
* Support frequency limits for ZynqMP (Mathias Tausen)
  - And continued by Mircea Caprioru, to read them from the IP cores

Changelog v3 -> v4:
* added patch 'clk: axi-clkgen: wrap limits in a struct and keep copy on the state object'
  this resets the rest of the patch-set to adapt to adjusting the limits
  on per-clock instance versus being global to the entire driver
  Recommended-by: Moritz Fischer <mdf@kernel.org>
    https://lore.kernel.org/linux-clk/20200924142108.GA60306@archbook/

Changelog v2 -> v3:
* https://lore.kernel.org/linux-clk/20200924065012.59605-1-alexandru.ardelean@analog.com/
* for patch 'include: fpga: adi-axi-common.h: add definitions for supported FPGAs'
  - fix whitespace found by checkpatch
  - add 'Acked-by: Moritz Fischer <mdf@kernel.org>'

Changelog v1 -> v2:
- https://lore.kernel.org/linux-clk/20200804110658.40911-1-alexandru.ardelean@analog.com/
- in patch 'include: fpga: adi-axi-common.h: add definitions for supported FPGAs'
  * converted enums to #define
  * added Intel FPGA definitions
  * added Device-Package definitions
  * added INTEL / XILINX in the define names
 definitions according to:
 https://github.com/analogdevicesinc/hdl/blob/4e438261aa319b1dda4c593c155218a93b1d869b/library/scripts/adi_intel_device_info_enc.tcl
 https://github.com/analogdevicesinc/hdl/blob/4e438261aa319b1dda4c593c155218a93b1d869b/library/scripts/adi_xilinx_device_info_enc.tcl


Alexandru Ardelean (1):
  clk: axi-clkgen: wrap limits in a struct and keep copy on the state
    object

Dragos Bogdan (1):
  clk: axi-clkgen: add support for ZynqMP (UltraScale)

Lars-Peter Clausen (2):
  clk: axi-clkgen: Add support for fractional dividers
  clk: axi-clkgen: Set power bits for fractional mode

Mathias Tausen (1):
  clk: axi-clkgen: Respect ZYNQMP PFD/VCO frequency limits

Mircea Caprioru (2):
  include: fpga: adi-axi-common.h: add definitions for supported FPGAs
  clk: axi-clkgen: Add support for FPGA info

 drivers/clk/Kconfig                 |   2 +-
 drivers/clk/clk-axi-clkgen.c        | 283 ++++++++++++++++++++++------
 include/linux/fpga/adi-axi-common.h | 103 ++++++++++
 3 files changed, 326 insertions(+), 62 deletions(-)

-- 
2.17.1


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

* [PATCH v4 1/7] clk: axi-clkgen: Add support for fractional dividers
  2020-09-29 14:44 [PATCH v4 0/7] clk: axi-clk-gen: misc updates to the driver Alexandru Ardelean
@ 2020-09-29 14:44 ` Alexandru Ardelean
  2020-09-29 14:44 ` [PATCH v4 2/7] clk: axi-clkgen: Set power bits for fractional mode Alexandru Ardelean
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Alexandru Ardelean @ 2020-09-29 14:44 UTC (permalink / raw)
  To: linux-clk, linux-fpga, linux-kernel
  Cc: mturquette, sboyd, mdf, ardeleanalex, Lars-Peter Clausen,
	Alexandru Ardelean

From: Lars-Peter Clausen <lars@metafoo.de>

The axi-clkgen has (optional) fractional dividers on the output clock
divider and feedback clock divider path. Utilizing the fractional dividers
allows for a better resolution of the output clock, being able to
synthesize more frequencies.

Rework the driver support to support the fractional register fields, both
for setting a new rate as well as reading back the current rate from the
hardware.

For setting the rate if no perfect divider settings were found in
non-fractional mode try again in fractional mode and see if better settings
can be found. This appears to be the recommended mode of operation.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/clk/clk-axi-clkgen.c | 180 +++++++++++++++++++++++++----------
 1 file changed, 129 insertions(+), 51 deletions(-)

diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
index 96f351785b41..1df03cc6d089 100644
--- a/drivers/clk/clk-axi-clkgen.c
+++ b/drivers/clk/clk-axi-clkgen.c
@@ -27,8 +27,10 @@
 
 #define AXI_CLKGEN_V2_DRP_STATUS_BUSY	BIT(16)
 
+#define MMCM_REG_CLKOUT5_2	0x07
 #define MMCM_REG_CLKOUT0_1	0x08
 #define MMCM_REG_CLKOUT0_2	0x09
+#define MMCM_REG_CLKOUT6_2	0x13
 #define MMCM_REG_CLK_FB1	0x14
 #define MMCM_REG_CLK_FB2	0x15
 #define MMCM_REG_CLK_DIV	0x16
@@ -40,6 +42,7 @@
 
 #define MMCM_CLKOUT_NOCOUNT	BIT(6)
 
+#define MMCM_CLK_DIV_DIVIDE	BIT(11)
 #define MMCM_CLK_DIV_NOCOUNT	BIT(12)
 
 struct axi_clkgen {
@@ -107,6 +110,8 @@ static void axi_clkgen_calc_params(unsigned long fin, unsigned long fout,
 	unsigned long d, d_min, d_max, _d_min, _d_max;
 	unsigned long m, m_min, m_max;
 	unsigned long f, dout, best_f, fvco;
+	unsigned long fract_shift = 0;
+	unsigned long fvco_min_fract, fvco_max_fract;
 
 	fin /= 1000;
 	fout /= 1000;
@@ -119,42 +124,89 @@ static void axi_clkgen_calc_params(unsigned long fin, unsigned long fout,
 	d_min = max_t(unsigned long, DIV_ROUND_UP(fin, fpfd_max), 1);
 	d_max = min_t(unsigned long, fin / fpfd_min, 80);
 
-	m_min = max_t(unsigned long, DIV_ROUND_UP(fvco_min, fin) * d_min, 1);
-	m_max = min_t(unsigned long, fvco_max * d_max / fin, 64);
+again:
+	fvco_min_fract = fvco_min << fract_shift;
+	fvco_max_fract = fvco_max << fract_shift;
+
+	m_min = max_t(unsigned long, DIV_ROUND_UP(fvco_min_fract, fin) * d_min, 1);
+	m_max = min_t(unsigned long, fvco_max_fract * d_max / fin, 64 << fract_shift);
 
 	for (m = m_min; m <= m_max; m++) {
-		_d_min = max(d_min, DIV_ROUND_UP(fin * m, fvco_max));
-		_d_max = min(d_max, fin * m / fvco_min);
+		_d_min = max(d_min, DIV_ROUND_UP(fin * m, fvco_max_fract));
+		_d_max = min(d_max, fin * m / fvco_min_fract);
 
 		for (d = _d_min; d <= _d_max; d++) {
 			fvco = fin * m / d;
 
 			dout = DIV_ROUND_CLOSEST(fvco, fout);
-			dout = clamp_t(unsigned long, dout, 1, 128);
+			dout = clamp_t(unsigned long, dout, 1, 128 << fract_shift);
 			f = fvco / dout;
 			if (abs(f - fout) < abs(best_f - fout)) {
 				best_f = f;
 				*best_d = d;
-				*best_m = m;
-				*best_dout = dout;
+				*best_m = m << (3 - fract_shift);
+				*best_dout = dout << (3 - fract_shift);
 				if (best_f == fout)
 					return;
 			}
 		}
 	}
+
+	/* Lets see if we find a better setting in fractional mode */
+	if (fract_shift == 0) {
+		fract_shift = 3;
+		goto again;
+	}
 }
 
-static void axi_clkgen_calc_clk_params(unsigned int divider, unsigned int *low,
-	unsigned int *high, unsigned int *edge, unsigned int *nocount)
+struct axi_clkgen_div_params {
+	unsigned int low;
+	unsigned int high;
+	unsigned int edge;
+	unsigned int nocount;
+	unsigned int frac_en;
+	unsigned int frac;
+	unsigned int frac_wf_f;
+	unsigned int frac_wf_r;
+	unsigned int frac_phase;
+};
+
+static void axi_clkgen_calc_clk_params(unsigned int divider,
+	unsigned int frac_divider, struct axi_clkgen_div_params *params)
 {
-	if (divider == 1)
-		*nocount = 1;
-	else
-		*nocount = 0;
 
-	*high = divider / 2;
-	*edge = divider % 2;
-	*low = divider - *high;
+	memset(params, 0x0, sizeof(*params));
+
+	if (divider == 1) {
+		params->nocount = 1;
+		return;
+	}
+
+	if (frac_divider == 0) {
+		params->high = divider / 2;
+		params->edge = divider % 2;
+		params->low = divider - params->high;
+	} else {
+		params->frac_en = 1;
+		params->frac = frac_divider;
+
+		params->high = divider / 2;
+		params->edge = divider % 2;
+		params->low = params->high;
+
+		if (params->edge == 0) {
+			params->high--;
+			params->frac_wf_r = 1;
+		}
+
+		if (params->edge == 0 || frac_divider == 1)
+			params->low--;
+		if (((params->edge == 0) ^ (frac_divider == 1)) ||
+			(divider == 2 && frac_divider == 1))
+			params->frac_wf_f = 1;
+
+		params->frac_phase = params->edge * 4 + frac_divider / 2;
+	}
 }
 
 static void axi_clkgen_write(struct axi_clkgen *axi_clkgen,
@@ -246,15 +298,28 @@ static struct axi_clkgen *clk_hw_to_axi_clkgen(struct clk_hw *clk_hw)
 	return container_of(clk_hw, struct axi_clkgen, clk_hw);
 }
 
+static void axi_clkgen_set_div(struct axi_clkgen *axi_clkgen,
+	unsigned int reg1, unsigned int reg2, unsigned int reg3,
+	struct axi_clkgen_div_params *params)
+{
+	axi_clkgen_mmcm_write(axi_clkgen, reg1,
+		(params->high << 6) | params->low, 0xefff);
+	axi_clkgen_mmcm_write(axi_clkgen, reg2,
+		(params->frac << 12) | (params->frac_en << 11) |
+		(params->frac_wf_r << 10) | (params->edge << 7) |
+		(params->nocount << 6), 0x7fff);
+	if (reg3 != 0) {
+		axi_clkgen_mmcm_write(axi_clkgen, reg3,
+			(params->frac_phase << 11) | (params->frac_wf_f << 10), 0x3c00);
+	}
+}
+
 static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
 	unsigned long rate, unsigned long parent_rate)
 {
 	struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
 	unsigned int d, m, dout;
-	unsigned int nocount;
-	unsigned int high;
-	unsigned int edge;
-	unsigned int low;
+	struct axi_clkgen_div_params params;
 	uint32_t filter;
 	uint32_t lock;
 
@@ -269,21 +334,18 @@ static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
 	filter = axi_clkgen_lookup_filter(m - 1);
 	lock = axi_clkgen_lookup_lock(m - 1);
 
-	axi_clkgen_calc_clk_params(dout, &low, &high, &edge, &nocount);
-	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLKOUT0_1,
-		(high << 6) | low, 0xefff);
-	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLKOUT0_2,
-		(edge << 7) | (nocount << 6), 0x03ff);
+	axi_clkgen_calc_clk_params(dout >> 3, dout & 0x7, &params);
+	axi_clkgen_set_div(axi_clkgen,  MMCM_REG_CLKOUT0_1, MMCM_REG_CLKOUT0_2,
+		MMCM_REG_CLKOUT5_2, &params);
 
-	axi_clkgen_calc_clk_params(d, &low, &high, &edge, &nocount);
+	axi_clkgen_calc_clk_params(d, 0, &params);
 	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_DIV,
-		(edge << 13) | (nocount << 12) | (high << 6) | low, 0x3fff);
+		(params.edge << 13) | (params.nocount << 12) |
+		(params.high << 6) | params.low, 0x3fff);
 
-	axi_clkgen_calc_clk_params(m, &low, &high, &edge, &nocount);
-	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_FB1,
-		(high << 6) | low, 0xefff);
-	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_FB2,
-		(edge << 7) | (nocount << 6), 0x03ff);
+	axi_clkgen_calc_clk_params(m >> 3, m & 0x7, &params);
+	axi_clkgen_set_div(axi_clkgen,  MMCM_REG_CLK_FB1, MMCM_REG_CLK_FB2,
+		MMCM_REG_CLKOUT6_2, &params);
 
 	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK1, lock & 0x3ff, 0x3ff);
 	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK2,
@@ -313,35 +375,51 @@ static long axi_clkgen_round_rate(struct clk_hw *hw, unsigned long rate,
 	return min_t(unsigned long long, tmp, LONG_MAX);
 }
 
+static unsigned int axi_clkgen_get_div(struct axi_clkgen *axi_clkgen,
+	unsigned int reg1, unsigned int reg2)
+{
+	unsigned int val1, val2;
+	unsigned int div;
+
+	axi_clkgen_mmcm_read(axi_clkgen, reg2, &val2);
+	if (val2 & MMCM_CLKOUT_NOCOUNT)
+		return 8;
+
+	axi_clkgen_mmcm_read(axi_clkgen, reg1, &val1);
+
+	div = (val1 & 0x3f) + ((val1 >> 6) & 0x3f);
+	div <<= 3;
+
+	if (val2 & MMCM_CLK_DIV_DIVIDE) {
+		if ((val2 & BIT(7)) && (val2 & 0x7000) != 0x1000)
+			div += 8;
+		else
+			div += 16;
+
+		div += (val2 >> 12) & 0x7;
+	}
+
+	return div;
+}
+
 static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw,
 	unsigned long parent_rate)
 {
 	struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
 	unsigned int d, m, dout;
-	unsigned int reg;
 	unsigned long long tmp;
+	unsigned int val;
 
-	axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLKOUT0_2, &reg);
-	if (reg & MMCM_CLKOUT_NOCOUNT) {
-		dout = 1;
-	} else {
-		axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLKOUT0_1, &reg);
-		dout = (reg & 0x3f) + ((reg >> 6) & 0x3f);
-	}
+	dout = axi_clkgen_get_div(axi_clkgen, MMCM_REG_CLKOUT0_1,
+		MMCM_REG_CLKOUT0_2);
+	m = axi_clkgen_get_div(axi_clkgen, MMCM_REG_CLK_FB1,
+		MMCM_REG_CLK_FB2);
 
-	axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_DIV, &reg);
-	if (reg & MMCM_CLK_DIV_NOCOUNT)
+	axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_DIV, &val);
+	if (val & MMCM_CLK_DIV_NOCOUNT)
 		d = 1;
 	else
-		d = (reg & 0x3f) + ((reg >> 6) & 0x3f);
-
-	axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_FB2, &reg);
-	if (reg & MMCM_CLKOUT_NOCOUNT) {
-		m = 1;
-	} else {
-		axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_FB1, &reg);
-		m = (reg & 0x3f) + ((reg >> 6) & 0x3f);
-	}
+		d = (val & 0x3f) + ((val >> 6) & 0x3f);
 
 	if (d == 0 || dout == 0)
 		return 0;
-- 
2.17.1


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

* [PATCH v4 2/7] clk: axi-clkgen: Set power bits for fractional mode
  2020-09-29 14:44 [PATCH v4 0/7] clk: axi-clk-gen: misc updates to the driver Alexandru Ardelean
  2020-09-29 14:44 ` [PATCH v4 1/7] clk: axi-clkgen: Add support for fractional dividers Alexandru Ardelean
@ 2020-09-29 14:44 ` Alexandru Ardelean
  2020-09-29 14:44 ` [PATCH v4 3/7] clk: axi-clkgen: add support for ZynqMP (UltraScale) Alexandru Ardelean
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Alexandru Ardelean @ 2020-09-29 14:44 UTC (permalink / raw)
  To: linux-clk, linux-fpga, linux-kernel
  Cc: mturquette, sboyd, mdf, ardeleanalex, Lars-Peter Clausen,
	Alexandru Ardelean

From: Lars-Peter Clausen <lars@metafoo.de>

Using the fractional dividers requires some additional power bits to be
set.

The fractional power bits are not documented and the current heuristic
for setting them seems be insufficient for some cases. Just always set all
the fractional power bits when in fractional mode.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/clk/clk-axi-clkgen.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
index 1df03cc6d089..14d803e6af62 100644
--- a/drivers/clk/clk-axi-clkgen.c
+++ b/drivers/clk/clk-axi-clkgen.c
@@ -37,6 +37,7 @@
 #define MMCM_REG_LOCK1		0x18
 #define MMCM_REG_LOCK2		0x19
 #define MMCM_REG_LOCK3		0x1a
+#define MMCM_REG_POWER		0x28
 #define MMCM_REG_FILTER1	0x4e
 #define MMCM_REG_FILTER2	0x4f
 
@@ -320,6 +321,7 @@ static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
 	struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
 	unsigned int d, m, dout;
 	struct axi_clkgen_div_params params;
+	uint32_t power = 0;
 	uint32_t filter;
 	uint32_t lock;
 
@@ -331,6 +333,11 @@ static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
 	if (d == 0 || dout == 0 || m == 0)
 		return -EINVAL;
 
+	if ((dout & 0x7) != 0 || (m & 0x7) != 0)
+		power |= 0x9800;
+
+	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_POWER, power, 0x9800);
+
 	filter = axi_clkgen_lookup_filter(m - 1);
 	lock = axi_clkgen_lookup_lock(m - 1);
 
-- 
2.17.1


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

* [PATCH v4 3/7] clk: axi-clkgen: add support for ZynqMP (UltraScale)
  2020-09-29 14:44 [PATCH v4 0/7] clk: axi-clk-gen: misc updates to the driver Alexandru Ardelean
  2020-09-29 14:44 ` [PATCH v4 1/7] clk: axi-clkgen: Add support for fractional dividers Alexandru Ardelean
  2020-09-29 14:44 ` [PATCH v4 2/7] clk: axi-clkgen: Set power bits for fractional mode Alexandru Ardelean
@ 2020-09-29 14:44 ` Alexandru Ardelean
  2020-09-29 14:44 ` [PATCH v4 4/7] clk: axi-clkgen: wrap limits in a struct and keep copy on the state object Alexandru Ardelean
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Alexandru Ardelean @ 2020-09-29 14:44 UTC (permalink / raw)
  To: linux-clk, linux-fpga, linux-kernel
  Cc: mturquette, sboyd, mdf, ardeleanalex, Dragos Bogdan, Alexandru Ardelean

From: Dragos Bogdan <dragos.bogdan@analog.com>

This IP core also works and is supported on the Xilinx ZynqMP (UltraScale)
FPGA boards.
This patch enables the driver to be available on these platforms as well.

Signed-off-by: Dragos Bogdan <dragos.bogdan@analog.com>
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/clk/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index b41aaed9bd51..6d76591c0bc4 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -239,7 +239,7 @@ config CLK_TWL6040
 
 config COMMON_CLK_AXI_CLKGEN
 	tristate "AXI clkgen driver"
-	depends on ARCH_ZYNQ || MICROBLAZE || COMPILE_TEST
+	depends on ARCH_ZYNQ || ARCH_ZYNQMP || MICROBLAZE || COMPILE_TEST
 	help
 	  Support for the Analog Devices axi-clkgen pcore clock generator for Xilinx
 	  FPGAs. It is commonly used in Analog Devices' reference designs.
-- 
2.17.1


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

* [PATCH v4 4/7] clk: axi-clkgen: wrap limits in a struct and keep copy on the state object
  2020-09-29 14:44 [PATCH v4 0/7] clk: axi-clk-gen: misc updates to the driver Alexandru Ardelean
                   ` (2 preceding siblings ...)
  2020-09-29 14:44 ` [PATCH v4 3/7] clk: axi-clkgen: add support for ZynqMP (UltraScale) Alexandru Ardelean
@ 2020-09-29 14:44 ` Alexandru Ardelean
  2020-09-29 14:44 ` [PATCH v4 5/7] clk: axi-clkgen: Respect ZYNQMP PFD/VCO frequency limits Alexandru Ardelean
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Alexandru Ardelean @ 2020-09-29 14:44 UTC (permalink / raw)
  To: linux-clk, linux-fpga, linux-kernel
  Cc: mturquette, sboyd, mdf, ardeleanalex, Alexandru Ardelean

Up until the these limits were global/hard-coded, since they are typically
limits of the fabric.

However, since this is an FPGA generated clock, this may run on setups
where one clock is on a fabric, and another one synthesized on another
fabric connected via PCIe, and then these limits need to be adjusted for
each instance of the AXI clock.

This change wraps the current constants in 'axi_clkgen_limits' struct and
the 'axi_clkgen' instance keeps a copy of these limits, which is
initialized at probe from the default limits.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/clk/clk-axi-clkgen.c | 39 ++++++++++++++++++++++++++----------
 1 file changed, 28 insertions(+), 11 deletions(-)

diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
index 14d803e6af62..4342b7735590 100644
--- a/drivers/clk/clk-axi-clkgen.c
+++ b/drivers/clk/clk-axi-clkgen.c
@@ -46,9 +46,17 @@
 #define MMCM_CLK_DIV_DIVIDE	BIT(11)
 #define MMCM_CLK_DIV_NOCOUNT	BIT(12)
 
+struct axi_clkgen_limits {
+	unsigned int fpfd_min;
+	unsigned int fpfd_max;
+	unsigned int fvco_min;
+	unsigned int fvco_max;
+};
+
 struct axi_clkgen {
 	void __iomem *base;
 	struct clk_hw clk_hw;
+	struct axi_clkgen_limits limits;
 };
 
 static uint32_t axi_clkgen_lookup_filter(unsigned int m)
@@ -100,12 +108,15 @@ static uint32_t axi_clkgen_lookup_lock(unsigned int m)
 	return 0x1f1f00fa;
 }
 
-static const unsigned int fpfd_min = 10000;
-static const unsigned int fpfd_max = 300000;
-static const unsigned int fvco_min = 600000;
-static const unsigned int fvco_max = 1200000;
+static const struct axi_clkgen_limits axi_clkgen_default_limits = {
+	.fpfd_min = 10000,
+	.fpfd_max = 300000,
+	.fvco_min = 600000,
+	.fvco_max = 1200000,
+};
 
-static void axi_clkgen_calc_params(unsigned long fin, unsigned long fout,
+static void axi_clkgen_calc_params(const struct axi_clkgen_limits *limits,
+	unsigned long fin, unsigned long fout,
 	unsigned int *best_d, unsigned int *best_m, unsigned int *best_dout)
 {
 	unsigned long d, d_min, d_max, _d_min, _d_max;
@@ -122,12 +133,12 @@ static void axi_clkgen_calc_params(unsigned long fin, unsigned long fout,
 	*best_m = 0;
 	*best_dout = 0;
 
-	d_min = max_t(unsigned long, DIV_ROUND_UP(fin, fpfd_max), 1);
-	d_max = min_t(unsigned long, fin / fpfd_min, 80);
+	d_min = max_t(unsigned long, DIV_ROUND_UP(fin, limits->fpfd_max), 1);
+	d_max = min_t(unsigned long, fin / limits->fpfd_min, 80);
 
 again:
-	fvco_min_fract = fvco_min << fract_shift;
-	fvco_max_fract = fvco_max << fract_shift;
+	fvco_min_fract = limits->fvco_min << fract_shift;
+	fvco_max_fract = limits->fvco_max << fract_shift;
 
 	m_min = max_t(unsigned long, DIV_ROUND_UP(fvco_min_fract, fin) * d_min, 1);
 	m_max = min_t(unsigned long, fvco_max_fract * d_max / fin, 64 << fract_shift);
@@ -319,6 +330,7 @@ static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
 	unsigned long rate, unsigned long parent_rate)
 {
 	struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
+	const struct axi_clkgen_limits *limits = &axi_clkgen->limits;
 	unsigned int d, m, dout;
 	struct axi_clkgen_div_params params;
 	uint32_t power = 0;
@@ -328,7 +340,7 @@ static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
 	if (parent_rate == 0 || rate == 0)
 		return -EINVAL;
 
-	axi_clkgen_calc_params(parent_rate, rate, &d, &m, &dout);
+	axi_clkgen_calc_params(limits, parent_rate, rate, &d, &m, &dout);
 
 	if (d == 0 || dout == 0 || m == 0)
 		return -EINVAL;
@@ -368,10 +380,12 @@ static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
 static long axi_clkgen_round_rate(struct clk_hw *hw, unsigned long rate,
 	unsigned long *parent_rate)
 {
+	struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(hw);
+	const struct axi_clkgen_limits *limits = &axi_clkgen->limits;
 	unsigned int d, m, dout;
 	unsigned long long tmp;
 
-	axi_clkgen_calc_params(*parent_rate, rate, &d, &m, &dout);
+	axi_clkgen_calc_params(limits, *parent_rate, rate, &d, &m, &dout);
 
 	if (d == 0 || dout == 0 || m == 0)
 		return -EINVAL;
@@ -527,6 +541,9 @@ static int axi_clkgen_probe(struct platform_device *pdev)
 			return -EINVAL;
 	}
 
+	memcpy(&axi_clkgen->limits, &axi_clkgen_default_limits,
+	       sizeof(axi_clkgen->limits));
+
 	clk_name = pdev->dev.of_node->name;
 	of_property_read_string(pdev->dev.of_node, "clock-output-names",
 		&clk_name);
-- 
2.17.1


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

* [PATCH v4 5/7] clk: axi-clkgen: Respect ZYNQMP PFD/VCO frequency limits
  2020-09-29 14:44 [PATCH v4 0/7] clk: axi-clk-gen: misc updates to the driver Alexandru Ardelean
                   ` (3 preceding siblings ...)
  2020-09-29 14:44 ` [PATCH v4 4/7] clk: axi-clkgen: wrap limits in a struct and keep copy on the state object Alexandru Ardelean
@ 2020-09-29 14:44 ` Alexandru Ardelean
  2020-09-29 14:44 ` [PATCH v4 6/7] include: fpga: adi-axi-common.h: add definitions for supported FPGAs Alexandru Ardelean
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Alexandru Ardelean @ 2020-09-29 14:44 UTC (permalink / raw)
  To: linux-clk, linux-fpga, linux-kernel
  Cc: mturquette, sboyd, mdf, ardeleanalex, Mathias Tausen, Alexandru Ardelean

From: Mathias Tausen <mta@gomspace.com>

Since axi-clkgen is now supported on ZYNQMP, make sure the max/min
frequencies of the PFD and VCO are respected.

Signed-off-by: Mathias Tausen <mta@gomspace.com>
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/clk/clk-axi-clkgen.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
index 4342b7735590..2319bb1c5c08 100644
--- a/drivers/clk/clk-axi-clkgen.c
+++ b/drivers/clk/clk-axi-clkgen.c
@@ -108,12 +108,21 @@ static uint32_t axi_clkgen_lookup_lock(unsigned int m)
 	return 0x1f1f00fa;
 }
 
+#ifdef ARCH_ZYNQMP
+static const struct axi_clkgen_limits axi_clkgen_default_limits = {
+	.fpfd_min = 10000,
+	.fpfd_max = 450000,
+	.fvco_min = 800000,
+	.fvco_max = 1600000,
+};
+#else
 static const struct axi_clkgen_limits axi_clkgen_default_limits = {
 	.fpfd_min = 10000,
 	.fpfd_max = 300000,
 	.fvco_min = 600000,
 	.fvco_max = 1200000,
 };
+#endif
 
 static void axi_clkgen_calc_params(const struct axi_clkgen_limits *limits,
 	unsigned long fin, unsigned long fout,
-- 
2.17.1


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

* [PATCH v4 6/7] include: fpga: adi-axi-common.h: add definitions for supported FPGAs
  2020-09-29 14:44 [PATCH v4 0/7] clk: axi-clk-gen: misc updates to the driver Alexandru Ardelean
                   ` (4 preceding siblings ...)
  2020-09-29 14:44 ` [PATCH v4 5/7] clk: axi-clkgen: Respect ZYNQMP PFD/VCO frequency limits Alexandru Ardelean
@ 2020-09-29 14:44 ` Alexandru Ardelean
  2020-09-29 14:44 ` [PATCH v4 7/7] clk: axi-clkgen: Add support for FPGA info Alexandru Ardelean
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Alexandru Ardelean @ 2020-09-29 14:44 UTC (permalink / raw)
  To: linux-clk, linux-fpga, linux-kernel
  Cc: mturquette, sboyd, mdf, ardeleanalex, Mircea Caprioru,
	Alexandru Ardelean

From: Mircea Caprioru <mircea.caprioru@analog.com>

All (newer) FPGA IP cores supported by Analog Devices, store information in
the synthesized designs. This information describes various parameters,
including the family of boards on which this is deployed, speed-grade, and
so on.

Currently, some of these definitions are deployed mostly on Xilinx boards,
but they have been considered also for FPGA boards from other vendors.

The register definitions are described at this link:
  https://wiki.analog.com/resources/fpga/docs/hdl/regmap
(the 'Base (common to all cores)' section).

Acked-by: Moritz Fischer <mdf@kernel.org>
Signed-off-by: Mircea Caprioru <mircea.caprioru@analog.com>
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 include/linux/fpga/adi-axi-common.h | 103 ++++++++++++++++++++++++++++
 1 file changed, 103 insertions(+)

diff --git a/include/linux/fpga/adi-axi-common.h b/include/linux/fpga/adi-axi-common.h
index 141ac3f251e6..1a7f18e3a384 100644
--- a/include/linux/fpga/adi-axi-common.h
+++ b/include/linux/fpga/adi-axi-common.h
@@ -13,6 +13,9 @@
 
 #define ADI_AXI_REG_VERSION			0x0000
 
+#define ADI_AXI_REG_FPGA_INFO			0x001C
+#define ADI_AXI_REG_FPGA_VOLTAGE		0x0140
+
 #define ADI_AXI_PCORE_VER(major, minor, patch)	\
 	(((major) << 16) | ((minor) << 8) | (patch))
 
@@ -20,4 +23,104 @@
 #define ADI_AXI_PCORE_VER_MINOR(version)	(((version) >> 8) & 0xff)
 #define ADI_AXI_PCORE_VER_PATCH(version)	((version) & 0xff)
 
+#define ADI_AXI_INFO_FPGA_VOLTAGE(val)		((val) & 0xffff)
+
+#define ADI_AXI_INFO_FPGA_TECH(info)		(((info) >> 24) & 0xff)
+#define ADI_AXI_INFO_FPGA_FAMILY(info)		(((info) >> 16) & 0xff)
+#define ADI_AXI_INFO_FPGA_SPEED_GRADE(info)	(((info) >> 8) & 0xff)
+#define ADI_AXI_INFO_FPGA_DEV_PACKAGE(info)	((info) & 0xff)
+
+/**
+ * FPGA Technology definitions
+ */
+#define ADI_AXI_FPGA_TECH_XILINX_UNKNOWN		0
+#define ADI_AXI_FPGA_TECH_XILINS_SERIES7		1
+#define ADI_AXI_FPGA_TECH_XILINX_ULTRASCALE		2
+#define ADI_AXI_FPGA_TECH_XILINX_ULTRASCALE_PLUS	3
+
+#define ADI_AXI_FPGA_TECH_INTEL_UNKNOWN			100
+#define ADI_AXI_FPGA_TECH_INTEL_CYCLONE_5		101
+#define ADI_AXI_FPGA_TECH_INTEL_CYCLONE_10		102
+#define ADI_AXI_FPGA_TECH_INTEL_ARRIA_10		103
+#define ADI_AXI_FPGA_TECH_INTEL_STRATIX_10		104
+
+/**
+ * FPGA Family definitions
+ */
+#define ADI_AXI_FPGA_FAMILY_UNKNOWN			0
+
+#define ADI_AXI_FPGA_FAMILY_XILINX_ARTIX		1
+#define ADI_AXI_FPGA_FAMILY_XILINX_KINTEX		2
+#define ADI_AXI_FPGA_FAMILY_XILINX_VIRTEX		3
+#define ADI_AXI_FPGA_FAMILY_XILINX_ZYNQ			4
+
+#define ADI_AXI_FPGA_FAMILY_INTEL_SX			1
+#define ADI_AXI_FPGA_FAMILY_INTEL_GX			2
+#define ADI_AXI_FPGA_FAMILY_INTEL_GT			3
+#define ADI_AXI_FPGA_FAMILY_INTEL_GZ			4
+
+/**
+ * FPGA Speed-grade definitions
+ */
+#define ADI_AXI_FPGA_SPEED_GRADE_UNKNOWN		0
+
+#define ADI_AXI_FPGA_SPEED_GRADE_XILINX_1		10
+#define ADI_AXI_FPGA_SPEED_GRADE_XILINX_1L		11
+#define ADI_AXI_FPGA_SPEED_GRADE_XILINX_1H		12
+#define ADI_AXI_FPGA_SPEED_GRADE_XILINX_1HV		13
+#define ADI_AXI_FPGA_SPEED_GRADE_XILINX_1LV		14
+#define ADI_AXI_FPGA_SPEED_GRADE_XILINX_2		20
+#define ADI_AXI_FPGA_SPEED_GRADE_XILINX_2L		21
+#define ADI_AXI_FPGA_SPEED_GRADE_XILINX_2LV		22
+#define ADI_AXI_FPGA_SPEED_GRADE_XILINX_3		30
+
+#define ADI_AXI_FPGA_SPEED_GRADE_INTEL_1		1
+#define ADI_AXI_FPGA_SPEED_GRADE_INTEL_2		2
+#define ADI_AXI_FPGA_SPEED_GRADE_INTEL_3		3
+#define ADI_AXI_FPGA_SPEED_GRADE_INTEL_4		4
+#define ADI_AXI_FPGA_SPEED_GRADE_INTEL_5		5
+#define ADI_AXI_FPGA_SPEED_GRADE_INTEL_6		6
+#define ADI_AXI_FPGA_SPEED_GRADE_INTEL_7		7
+#define ADI_AXI_FPGA_SPEED_GRADE_INTEL_8		8
+#define ADI_AXI_FPGA_SPEED_GRADE_INTEL_9		9
+
+/**
+ * FPGA Device Package definitions
+ */
+#define ADI_AXI_FPGA_DEV_PACKAGE_UNKNOWN		0
+
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_RF		1
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_FL		2
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_FF		3
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_FB		4
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_HC		5
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_FH		6
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_CS		7
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_CP		8
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_FT		9
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_FG		10
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_SB		11
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_RB		12
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_RS		13
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_CL		14
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_SF		15
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_BA		16
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_FA		17
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_FS		18
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_FI		19
+
+#define ADI_AXI_FPGA_DEV_PACKAGE_INTEL_BGA		1
+#define ADI_AXI_FPGA_DEV_PACKAGE_INTEL_PGA		2
+#define ADI_AXI_FPGA_DEV_PACKAGE_INTEL_FBGA		3
+#define ADI_AXI_FPGA_DEV_PACKAGE_INTEL_HBGA		4
+#define ADI_AXI_FPGA_DEV_PACKAGE_INTEL_PDIP		5
+#define ADI_AXI_FPGA_DEV_PACKAGE_INTEL_EQFP		6
+#define ADI_AXI_FPGA_DEV_PACKAGE_INTEL_PLCC		7
+#define ADI_AXI_FPGA_DEV_PACKAGE_INTEL_PQFP		8
+#define ADI_AXI_FPGA_DEV_PACKAGE_INTEL_RQFP		9
+#define ADI_AXI_FPGA_DEV_PACKAGE_INTEL_TQFP		10
+#define ADI_AXI_FPGA_DEV_PACKAGE_INTEL_UBGA		11
+#define ADI_AXI_FPGA_DEV_PACKAGE_INTEL_UFBGA		12
+#define ADI_AXI_FPGA_DEV_PACKAGE_INTEL_MBGA		13
+
 #endif /* ADI_AXI_COMMON_H_ */
-- 
2.17.1


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

* [PATCH v4 7/7] clk: axi-clkgen: Add support for FPGA info
  2020-09-29 14:44 [PATCH v4 0/7] clk: axi-clk-gen: misc updates to the driver Alexandru Ardelean
                   ` (5 preceding siblings ...)
  2020-09-29 14:44 ` [PATCH v4 6/7] include: fpga: adi-axi-common.h: add definitions for supported FPGAs Alexandru Ardelean
@ 2020-09-29 14:44 ` Alexandru Ardelean
  2020-09-29 14:44 ` [PATCH v4 0/7] clk: axi-clk-gen: misc updates to the driver Alexandru Ardelean
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Alexandru Ardelean @ 2020-09-29 14:44 UTC (permalink / raw)
  To: linux-clk, linux-fpga, linux-kernel
  Cc: mturquette, sboyd, mdf, ardeleanalex, Mircea Caprioru,
	Alexandru Ardelean

From: Mircea Caprioru <mircea.caprioru@analog.com>

This patch adds support for vco maximum and minimum ranges in accordance
with fpga speed grade, voltage, device package, technology and family. This
new information is extracted from two new registers implemented in the ip
core: ADI_REG_FPGA_INFO and ADI_REG_FPGA_VOLTAGE, which are stored in the
'include/linux/fpga/adi-axi-common.h' file as they are common to all ADI
FPGA cores.

Signed-off-by: Mircea Caprioru <mircea.caprioru@analog.com>
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/clk/clk-axi-clkgen.c | 52 +++++++++++++++++++++++++++++++++++-
 1 file changed, 51 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
index 2319bb1c5c08..46fd228b0733 100644
--- a/drivers/clk/clk-axi-clkgen.c
+++ b/drivers/clk/clk-axi-clkgen.c
@@ -8,6 +8,7 @@
 
 #include <linux/platform_device.h>
 #include <linux/clk-provider.h>
+#include <linux/fpga/adi-axi-common.h>
 #include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/of.h>
@@ -242,6 +243,50 @@ static void axi_clkgen_read(struct axi_clkgen *axi_clkgen,
 	*val = readl(axi_clkgen->base + reg);
 }
 
+static void axi_clkgen_setup_ranges(struct axi_clkgen *axi_clkgen)
+{
+	struct axi_clkgen_limits *limits = &axi_clkgen->limits;
+	unsigned int reg_value;
+	unsigned int tech, family, speed_grade, voltage;
+
+	axi_clkgen_read(axi_clkgen, ADI_AXI_REG_FPGA_INFO, &reg_value);
+	tech = ADI_AXI_INFO_FPGA_TECH(reg_value);
+	family = ADI_AXI_INFO_FPGA_FAMILY(reg_value);
+	speed_grade = ADI_AXI_INFO_FPGA_SPEED_GRADE(reg_value);
+
+	axi_clkgen_read(axi_clkgen, ADI_AXI_REG_FPGA_VOLTAGE, &reg_value);
+	voltage = ADI_AXI_INFO_FPGA_VOLTAGE(reg_value);
+
+	switch (speed_grade) {
+	case ADI_AXI_FPGA_SPEED_GRADE_XILINX_1 ... ADI_AXI_FPGA_SPEED_GRADE_XILINX_1LV:
+		limits->fvco_max = 1200000;
+		limits->fpfd_max = 450000;
+		break;
+	case ADI_AXI_FPGA_SPEED_GRADE_XILINX_2 ... ADI_AXI_FPGA_SPEED_GRADE_XILINX_2LV:
+		limits->fvco_max = 1440000;
+		limits->fpfd_max = 500000;
+		if ((family == ADI_AXI_FPGA_FAMILY_XILINX_KINTEX) |
+		    (family == ADI_AXI_FPGA_FAMILY_XILINX_ARTIX)) {
+			if (voltage < 950) {
+				limits->fvco_max = 1200000;
+				limits->fpfd_max = 450000;
+			}
+		}
+		break;
+	case ADI_AXI_FPGA_SPEED_GRADE_XILINX_3:
+		limits->fvco_max = 1600000;
+		limits->fpfd_max = 550000;
+		break;
+	default:
+		break;
+	};
+
+	if (tech == ADI_AXI_FPGA_TECH_XILINX_ULTRASCALE_PLUS) {
+		limits->fvco_max = 1600000;
+		limits->fvco_min = 800000;
+	}
+}
+
 static int axi_clkgen_wait_non_busy(struct axi_clkgen *axi_clkgen)
 {
 	unsigned int timeout = 10000;
@@ -521,7 +566,7 @@ static int axi_clkgen_probe(struct platform_device *pdev)
 	const char *parent_names[2];
 	const char *clk_name;
 	struct resource *mem;
-	unsigned int i;
+	unsigned int i, ver;
 	int ret;
 
 	if (!pdev->dev.of_node)
@@ -553,6 +598,11 @@ static int axi_clkgen_probe(struct platform_device *pdev)
 	memcpy(&axi_clkgen->limits, &axi_clkgen_default_limits,
 	       sizeof(axi_clkgen->limits));
 
+	axi_clkgen_read(axi_clkgen, ADI_AXI_REG_VERSION, &ver);
+
+	if (ADI_AXI_PCORE_VER_MAJOR(ver) > 0x04)
+		axi_clkgen_setup_ranges(axi_clkgen);
+
 	clk_name = pdev->dev.of_node->name;
 	of_property_read_string(pdev->dev.of_node, "clock-output-names",
 		&clk_name);
-- 
2.17.1


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

* [PATCH v4 0/7] clk: axi-clk-gen: misc updates to the driver
  2020-09-29 14:44 [PATCH v4 0/7] clk: axi-clk-gen: misc updates to the driver Alexandru Ardelean
                   ` (6 preceding siblings ...)
  2020-09-29 14:44 ` [PATCH v4 7/7] clk: axi-clkgen: Add support for FPGA info Alexandru Ardelean
@ 2020-09-29 14:44 ` Alexandru Ardelean
  2020-09-29 14:44 ` [PATCH v4 1/7] clk: axi-clkgen: Add support for fractional dividers Alexandru Ardelean
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Alexandru Ardelean @ 2020-09-29 14:44 UTC (permalink / raw)
  To: linux-clk, linux-fpga, linux-kernel
  Cc: mturquette, sboyd, mdf, ardeleanalex, Alexandru Ardelean

These patches synchronize the driver with the current state in the
Analog Devices Linux tree:
  https://github.com/analogdevicesinc/linux/

They have been in the tree for about 2-3, so they did receive some
testing.

Highlights are:
* Add support for fractional dividers (Lars-Peter Clausen)
* Enable support for ZynqMP (UltraScale) (Dragos Bogdan)
* Support frequency limits for ZynqMP (Mathias Tausen)
  - And continued by Mircea Caprioru, to read them from the IP cores

Changelog v3 -> v4:
* added patch 'clk: axi-clkgen: wrap limits in a struct and keep copy on the state object'
  this resets the rest of the patch-set to adapt to adjusting the limits
  on per-clock instance versus being global to the entire driver
  Recommended-by: Moritz Fischer <mdf@kernel.org>
    https://lore.kernel.org/linux-clk/20200924142108.GA60306@archbook/

Changelog v2 -> v3:
* https://lore.kernel.org/linux-clk/20200924065012.59605-1-alexandru.ardelean@analog.com/
* for patch 'include: fpga: adi-axi-common.h: add definitions for supported FPGAs'
  - fix whitespace found by checkpatch
  - add 'Acked-by: Moritz Fischer <mdf@kernel.org>'

Changelog v1 -> v2:
- https://lore.kernel.org/linux-clk/20200804110658.40911-1-alexandru.ardelean@analog.com/
- in patch 'include: fpga: adi-axi-common.h: add definitions for supported FPGAs'
  * converted enums to #define
  * added Intel FPGA definitions
  * added Device-Package definitions
  * added INTEL / XILINX in the define names
 definitions according to:
 https://github.com/analogdevicesinc/hdl/blob/4e438261aa319b1dda4c593c155218a93b1d869b/library/scripts/adi_intel_device_info_enc.tcl
 https://github.com/analogdevicesinc/hdl/blob/4e438261aa319b1dda4c593c155218a93b1d869b/library/scripts/adi_xilinx_device_info_enc.tcl


Alexandru Ardelean (1):
  clk: axi-clkgen: wrap limits in a struct and keep copy on the state
    object

Dragos Bogdan (1):
  clk: axi-clkgen: add support for ZynqMP (UltraScale)

Lars-Peter Clausen (2):
  clk: axi-clkgen: Add support for fractional dividers
  clk: axi-clkgen: Set power bits for fractional mode

Mathias Tausen (1):
  clk: axi-clkgen: Respect ZYNQMP PFD/VCO frequency limits

Mircea Caprioru (2):
  include: fpga: adi-axi-common.h: add definitions for supported FPGAs
  clk: axi-clkgen: Add support for FPGA info

 drivers/clk/Kconfig                 |   2 +-
 drivers/clk/clk-axi-clkgen.c        | 283 ++++++++++++++++++++++------
 include/linux/fpga/adi-axi-common.h | 103 ++++++++++
 3 files changed, 326 insertions(+), 62 deletions(-)

-- 
2.17.1


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

* [PATCH v4 1/7] clk: axi-clkgen: Add support for fractional dividers
  2020-09-29 14:44 [PATCH v4 0/7] clk: axi-clk-gen: misc updates to the driver Alexandru Ardelean
                   ` (7 preceding siblings ...)
  2020-09-29 14:44 ` [PATCH v4 0/7] clk: axi-clk-gen: misc updates to the driver Alexandru Ardelean
@ 2020-09-29 14:44 ` Alexandru Ardelean
  2020-09-29 14:44 ` [PATCH v4 2/7] clk: axi-clkgen: Set power bits for fractional mode Alexandru Ardelean
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Alexandru Ardelean @ 2020-09-29 14:44 UTC (permalink / raw)
  To: linux-clk, linux-fpga, linux-kernel
  Cc: mturquette, sboyd, mdf, ardeleanalex, Lars-Peter Clausen,
	Alexandru Ardelean

From: Lars-Peter Clausen <lars@metafoo.de>

The axi-clkgen has (optional) fractional dividers on the output clock
divider and feedback clock divider path. Utilizing the fractional dividers
allows for a better resolution of the output clock, being able to
synthesize more frequencies.

Rework the driver support to support the fractional register fields, both
for setting a new rate as well as reading back the current rate from the
hardware.

For setting the rate if no perfect divider settings were found in
non-fractional mode try again in fractional mode and see if better settings
can be found. This appears to be the recommended mode of operation.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/clk/clk-axi-clkgen.c | 180 +++++++++++++++++++++++++----------
 1 file changed, 129 insertions(+), 51 deletions(-)

diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
index 96f351785b41..1df03cc6d089 100644
--- a/drivers/clk/clk-axi-clkgen.c
+++ b/drivers/clk/clk-axi-clkgen.c
@@ -27,8 +27,10 @@
 
 #define AXI_CLKGEN_V2_DRP_STATUS_BUSY	BIT(16)
 
+#define MMCM_REG_CLKOUT5_2	0x07
 #define MMCM_REG_CLKOUT0_1	0x08
 #define MMCM_REG_CLKOUT0_2	0x09
+#define MMCM_REG_CLKOUT6_2	0x13
 #define MMCM_REG_CLK_FB1	0x14
 #define MMCM_REG_CLK_FB2	0x15
 #define MMCM_REG_CLK_DIV	0x16
@@ -40,6 +42,7 @@
 
 #define MMCM_CLKOUT_NOCOUNT	BIT(6)
 
+#define MMCM_CLK_DIV_DIVIDE	BIT(11)
 #define MMCM_CLK_DIV_NOCOUNT	BIT(12)
 
 struct axi_clkgen {
@@ -107,6 +110,8 @@ static void axi_clkgen_calc_params(unsigned long fin, unsigned long fout,
 	unsigned long d, d_min, d_max, _d_min, _d_max;
 	unsigned long m, m_min, m_max;
 	unsigned long f, dout, best_f, fvco;
+	unsigned long fract_shift = 0;
+	unsigned long fvco_min_fract, fvco_max_fract;
 
 	fin /= 1000;
 	fout /= 1000;
@@ -119,42 +124,89 @@ static void axi_clkgen_calc_params(unsigned long fin, unsigned long fout,
 	d_min = max_t(unsigned long, DIV_ROUND_UP(fin, fpfd_max), 1);
 	d_max = min_t(unsigned long, fin / fpfd_min, 80);
 
-	m_min = max_t(unsigned long, DIV_ROUND_UP(fvco_min, fin) * d_min, 1);
-	m_max = min_t(unsigned long, fvco_max * d_max / fin, 64);
+again:
+	fvco_min_fract = fvco_min << fract_shift;
+	fvco_max_fract = fvco_max << fract_shift;
+
+	m_min = max_t(unsigned long, DIV_ROUND_UP(fvco_min_fract, fin) * d_min, 1);
+	m_max = min_t(unsigned long, fvco_max_fract * d_max / fin, 64 << fract_shift);
 
 	for (m = m_min; m <= m_max; m++) {
-		_d_min = max(d_min, DIV_ROUND_UP(fin * m, fvco_max));
-		_d_max = min(d_max, fin * m / fvco_min);
+		_d_min = max(d_min, DIV_ROUND_UP(fin * m, fvco_max_fract));
+		_d_max = min(d_max, fin * m / fvco_min_fract);
 
 		for (d = _d_min; d <= _d_max; d++) {
 			fvco = fin * m / d;
 
 			dout = DIV_ROUND_CLOSEST(fvco, fout);
-			dout = clamp_t(unsigned long, dout, 1, 128);
+			dout = clamp_t(unsigned long, dout, 1, 128 << fract_shift);
 			f = fvco / dout;
 			if (abs(f - fout) < abs(best_f - fout)) {
 				best_f = f;
 				*best_d = d;
-				*best_m = m;
-				*best_dout = dout;
+				*best_m = m << (3 - fract_shift);
+				*best_dout = dout << (3 - fract_shift);
 				if (best_f == fout)
 					return;
 			}
 		}
 	}
+
+	/* Lets see if we find a better setting in fractional mode */
+	if (fract_shift == 0) {
+		fract_shift = 3;
+		goto again;
+	}
 }
 
-static void axi_clkgen_calc_clk_params(unsigned int divider, unsigned int *low,
-	unsigned int *high, unsigned int *edge, unsigned int *nocount)
+struct axi_clkgen_div_params {
+	unsigned int low;
+	unsigned int high;
+	unsigned int edge;
+	unsigned int nocount;
+	unsigned int frac_en;
+	unsigned int frac;
+	unsigned int frac_wf_f;
+	unsigned int frac_wf_r;
+	unsigned int frac_phase;
+};
+
+static void axi_clkgen_calc_clk_params(unsigned int divider,
+	unsigned int frac_divider, struct axi_clkgen_div_params *params)
 {
-	if (divider == 1)
-		*nocount = 1;
-	else
-		*nocount = 0;
 
-	*high = divider / 2;
-	*edge = divider % 2;
-	*low = divider - *high;
+	memset(params, 0x0, sizeof(*params));
+
+	if (divider == 1) {
+		params->nocount = 1;
+		return;
+	}
+
+	if (frac_divider == 0) {
+		params->high = divider / 2;
+		params->edge = divider % 2;
+		params->low = divider - params->high;
+	} else {
+		params->frac_en = 1;
+		params->frac = frac_divider;
+
+		params->high = divider / 2;
+		params->edge = divider % 2;
+		params->low = params->high;
+
+		if (params->edge == 0) {
+			params->high--;
+			params->frac_wf_r = 1;
+		}
+
+		if (params->edge == 0 || frac_divider == 1)
+			params->low--;
+		if (((params->edge == 0) ^ (frac_divider == 1)) ||
+			(divider == 2 && frac_divider == 1))
+			params->frac_wf_f = 1;
+
+		params->frac_phase = params->edge * 4 + frac_divider / 2;
+	}
 }
 
 static void axi_clkgen_write(struct axi_clkgen *axi_clkgen,
@@ -246,15 +298,28 @@ static struct axi_clkgen *clk_hw_to_axi_clkgen(struct clk_hw *clk_hw)
 	return container_of(clk_hw, struct axi_clkgen, clk_hw);
 }
 
+static void axi_clkgen_set_div(struct axi_clkgen *axi_clkgen,
+	unsigned int reg1, unsigned int reg2, unsigned int reg3,
+	struct axi_clkgen_div_params *params)
+{
+	axi_clkgen_mmcm_write(axi_clkgen, reg1,
+		(params->high << 6) | params->low, 0xefff);
+	axi_clkgen_mmcm_write(axi_clkgen, reg2,
+		(params->frac << 12) | (params->frac_en << 11) |
+		(params->frac_wf_r << 10) | (params->edge << 7) |
+		(params->nocount << 6), 0x7fff);
+	if (reg3 != 0) {
+		axi_clkgen_mmcm_write(axi_clkgen, reg3,
+			(params->frac_phase << 11) | (params->frac_wf_f << 10), 0x3c00);
+	}
+}
+
 static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
 	unsigned long rate, unsigned long parent_rate)
 {
 	struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
 	unsigned int d, m, dout;
-	unsigned int nocount;
-	unsigned int high;
-	unsigned int edge;
-	unsigned int low;
+	struct axi_clkgen_div_params params;
 	uint32_t filter;
 	uint32_t lock;
 
@@ -269,21 +334,18 @@ static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
 	filter = axi_clkgen_lookup_filter(m - 1);
 	lock = axi_clkgen_lookup_lock(m - 1);
 
-	axi_clkgen_calc_clk_params(dout, &low, &high, &edge, &nocount);
-	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLKOUT0_1,
-		(high << 6) | low, 0xefff);
-	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLKOUT0_2,
-		(edge << 7) | (nocount << 6), 0x03ff);
+	axi_clkgen_calc_clk_params(dout >> 3, dout & 0x7, &params);
+	axi_clkgen_set_div(axi_clkgen,  MMCM_REG_CLKOUT0_1, MMCM_REG_CLKOUT0_2,
+		MMCM_REG_CLKOUT5_2, &params);
 
-	axi_clkgen_calc_clk_params(d, &low, &high, &edge, &nocount);
+	axi_clkgen_calc_clk_params(d, 0, &params);
 	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_DIV,
-		(edge << 13) | (nocount << 12) | (high << 6) | low, 0x3fff);
+		(params.edge << 13) | (params.nocount << 12) |
+		(params.high << 6) | params.low, 0x3fff);
 
-	axi_clkgen_calc_clk_params(m, &low, &high, &edge, &nocount);
-	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_FB1,
-		(high << 6) | low, 0xefff);
-	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_FB2,
-		(edge << 7) | (nocount << 6), 0x03ff);
+	axi_clkgen_calc_clk_params(m >> 3, m & 0x7, &params);
+	axi_clkgen_set_div(axi_clkgen,  MMCM_REG_CLK_FB1, MMCM_REG_CLK_FB2,
+		MMCM_REG_CLKOUT6_2, &params);
 
 	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK1, lock & 0x3ff, 0x3ff);
 	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK2,
@@ -313,35 +375,51 @@ static long axi_clkgen_round_rate(struct clk_hw *hw, unsigned long rate,
 	return min_t(unsigned long long, tmp, LONG_MAX);
 }
 
+static unsigned int axi_clkgen_get_div(struct axi_clkgen *axi_clkgen,
+	unsigned int reg1, unsigned int reg2)
+{
+	unsigned int val1, val2;
+	unsigned int div;
+
+	axi_clkgen_mmcm_read(axi_clkgen, reg2, &val2);
+	if (val2 & MMCM_CLKOUT_NOCOUNT)
+		return 8;
+
+	axi_clkgen_mmcm_read(axi_clkgen, reg1, &val1);
+
+	div = (val1 & 0x3f) + ((val1 >> 6) & 0x3f);
+	div <<= 3;
+
+	if (val2 & MMCM_CLK_DIV_DIVIDE) {
+		if ((val2 & BIT(7)) && (val2 & 0x7000) != 0x1000)
+			div += 8;
+		else
+			div += 16;
+
+		div += (val2 >> 12) & 0x7;
+	}
+
+	return div;
+}
+
 static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw,
 	unsigned long parent_rate)
 {
 	struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
 	unsigned int d, m, dout;
-	unsigned int reg;
 	unsigned long long tmp;
+	unsigned int val;
 
-	axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLKOUT0_2, &reg);
-	if (reg & MMCM_CLKOUT_NOCOUNT) {
-		dout = 1;
-	} else {
-		axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLKOUT0_1, &reg);
-		dout = (reg & 0x3f) + ((reg >> 6) & 0x3f);
-	}
+	dout = axi_clkgen_get_div(axi_clkgen, MMCM_REG_CLKOUT0_1,
+		MMCM_REG_CLKOUT0_2);
+	m = axi_clkgen_get_div(axi_clkgen, MMCM_REG_CLK_FB1,
+		MMCM_REG_CLK_FB2);
 
-	axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_DIV, &reg);
-	if (reg & MMCM_CLK_DIV_NOCOUNT)
+	axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_DIV, &val);
+	if (val & MMCM_CLK_DIV_NOCOUNT)
 		d = 1;
 	else
-		d = (reg & 0x3f) + ((reg >> 6) & 0x3f);
-
-	axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_FB2, &reg);
-	if (reg & MMCM_CLKOUT_NOCOUNT) {
-		m = 1;
-	} else {
-		axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_FB1, &reg);
-		m = (reg & 0x3f) + ((reg >> 6) & 0x3f);
-	}
+		d = (val & 0x3f) + ((val >> 6) & 0x3f);
 
 	if (d == 0 || dout == 0)
 		return 0;
-- 
2.17.1


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

* [PATCH v4 2/7] clk: axi-clkgen: Set power bits for fractional mode
  2020-09-29 14:44 [PATCH v4 0/7] clk: axi-clk-gen: misc updates to the driver Alexandru Ardelean
                   ` (8 preceding siblings ...)
  2020-09-29 14:44 ` [PATCH v4 1/7] clk: axi-clkgen: Add support for fractional dividers Alexandru Ardelean
@ 2020-09-29 14:44 ` Alexandru Ardelean
  2020-09-29 14:44 ` [PATCH v4 3/7] clk: axi-clkgen: add support for ZynqMP (UltraScale) Alexandru Ardelean
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Alexandru Ardelean @ 2020-09-29 14:44 UTC (permalink / raw)
  To: linux-clk, linux-fpga, linux-kernel
  Cc: mturquette, sboyd, mdf, ardeleanalex, Lars-Peter Clausen,
	Alexandru Ardelean

From: Lars-Peter Clausen <lars@metafoo.de>

Using the fractional dividers requires some additional power bits to be
set.

The fractional power bits are not documented and the current heuristic
for setting them seems be insufficient for some cases. Just always set all
the fractional power bits when in fractional mode.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/clk/clk-axi-clkgen.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
index 1df03cc6d089..14d803e6af62 100644
--- a/drivers/clk/clk-axi-clkgen.c
+++ b/drivers/clk/clk-axi-clkgen.c
@@ -37,6 +37,7 @@
 #define MMCM_REG_LOCK1		0x18
 #define MMCM_REG_LOCK2		0x19
 #define MMCM_REG_LOCK3		0x1a
+#define MMCM_REG_POWER		0x28
 #define MMCM_REG_FILTER1	0x4e
 #define MMCM_REG_FILTER2	0x4f
 
@@ -320,6 +321,7 @@ static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
 	struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
 	unsigned int d, m, dout;
 	struct axi_clkgen_div_params params;
+	uint32_t power = 0;
 	uint32_t filter;
 	uint32_t lock;
 
@@ -331,6 +333,11 @@ static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
 	if (d == 0 || dout == 0 || m == 0)
 		return -EINVAL;
 
+	if ((dout & 0x7) != 0 || (m & 0x7) != 0)
+		power |= 0x9800;
+
+	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_POWER, power, 0x9800);
+
 	filter = axi_clkgen_lookup_filter(m - 1);
 	lock = axi_clkgen_lookup_lock(m - 1);
 
-- 
2.17.1


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

* [PATCH v4 3/7] clk: axi-clkgen: add support for ZynqMP (UltraScale)
  2020-09-29 14:44 [PATCH v4 0/7] clk: axi-clk-gen: misc updates to the driver Alexandru Ardelean
                   ` (9 preceding siblings ...)
  2020-09-29 14:44 ` [PATCH v4 2/7] clk: axi-clkgen: Set power bits for fractional mode Alexandru Ardelean
@ 2020-09-29 14:44 ` Alexandru Ardelean
  2020-09-29 14:44 ` [PATCH v4 4/7] clk: axi-clkgen: wrap limits in a struct and keep copy on the state object Alexandru Ardelean
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Alexandru Ardelean @ 2020-09-29 14:44 UTC (permalink / raw)
  To: linux-clk, linux-fpga, linux-kernel
  Cc: mturquette, sboyd, mdf, ardeleanalex, Dragos Bogdan, Alexandru Ardelean

From: Dragos Bogdan <dragos.bogdan@analog.com>

This IP core also works and is supported on the Xilinx ZynqMP (UltraScale)
FPGA boards.
This patch enables the driver to be available on these platforms as well.

Signed-off-by: Dragos Bogdan <dragos.bogdan@analog.com>
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/clk/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index b41aaed9bd51..6d76591c0bc4 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -239,7 +239,7 @@ config CLK_TWL6040
 
 config COMMON_CLK_AXI_CLKGEN
 	tristate "AXI clkgen driver"
-	depends on ARCH_ZYNQ || MICROBLAZE || COMPILE_TEST
+	depends on ARCH_ZYNQ || ARCH_ZYNQMP || MICROBLAZE || COMPILE_TEST
 	help
 	  Support for the Analog Devices axi-clkgen pcore clock generator for Xilinx
 	  FPGAs. It is commonly used in Analog Devices' reference designs.
-- 
2.17.1


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

* [PATCH v4 4/7] clk: axi-clkgen: wrap limits in a struct and keep copy on the state object
  2020-09-29 14:44 [PATCH v4 0/7] clk: axi-clk-gen: misc updates to the driver Alexandru Ardelean
                   ` (10 preceding siblings ...)
  2020-09-29 14:44 ` [PATCH v4 3/7] clk: axi-clkgen: add support for ZynqMP (UltraScale) Alexandru Ardelean
@ 2020-09-29 14:44 ` Alexandru Ardelean
  2020-09-29 14:44 ` [PATCH v4 5/7] clk: axi-clkgen: Respect ZYNQMP PFD/VCO frequency limits Alexandru Ardelean
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Alexandru Ardelean @ 2020-09-29 14:44 UTC (permalink / raw)
  To: linux-clk, linux-fpga, linux-kernel
  Cc: mturquette, sboyd, mdf, ardeleanalex, Alexandru Ardelean

Up until the these limits were global/hard-coded, since they are typically
limits of the fabric.

However, since this is an FPGA generated clock, this may run on setups
where one clock is on a fabric, and another one synthesized on another
fabric connected via PCIe, and then these limits need to be adjusted for
each instance of the AXI clock.

This change wraps the current constants in 'axi_clkgen_limits' struct and
the 'axi_clkgen' instance keeps a copy of these limits, which is
initialized at probe from the default limits.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/clk/clk-axi-clkgen.c | 39 ++++++++++++++++++++++++++----------
 1 file changed, 28 insertions(+), 11 deletions(-)

diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
index 14d803e6af62..4342b7735590 100644
--- a/drivers/clk/clk-axi-clkgen.c
+++ b/drivers/clk/clk-axi-clkgen.c
@@ -46,9 +46,17 @@
 #define MMCM_CLK_DIV_DIVIDE	BIT(11)
 #define MMCM_CLK_DIV_NOCOUNT	BIT(12)
 
+struct axi_clkgen_limits {
+	unsigned int fpfd_min;
+	unsigned int fpfd_max;
+	unsigned int fvco_min;
+	unsigned int fvco_max;
+};
+
 struct axi_clkgen {
 	void __iomem *base;
 	struct clk_hw clk_hw;
+	struct axi_clkgen_limits limits;
 };
 
 static uint32_t axi_clkgen_lookup_filter(unsigned int m)
@@ -100,12 +108,15 @@ static uint32_t axi_clkgen_lookup_lock(unsigned int m)
 	return 0x1f1f00fa;
 }
 
-static const unsigned int fpfd_min = 10000;
-static const unsigned int fpfd_max = 300000;
-static const unsigned int fvco_min = 600000;
-static const unsigned int fvco_max = 1200000;
+static const struct axi_clkgen_limits axi_clkgen_default_limits = {
+	.fpfd_min = 10000,
+	.fpfd_max = 300000,
+	.fvco_min = 600000,
+	.fvco_max = 1200000,
+};
 
-static void axi_clkgen_calc_params(unsigned long fin, unsigned long fout,
+static void axi_clkgen_calc_params(const struct axi_clkgen_limits *limits,
+	unsigned long fin, unsigned long fout,
 	unsigned int *best_d, unsigned int *best_m, unsigned int *best_dout)
 {
 	unsigned long d, d_min, d_max, _d_min, _d_max;
@@ -122,12 +133,12 @@ static void axi_clkgen_calc_params(unsigned long fin, unsigned long fout,
 	*best_m = 0;
 	*best_dout = 0;
 
-	d_min = max_t(unsigned long, DIV_ROUND_UP(fin, fpfd_max), 1);
-	d_max = min_t(unsigned long, fin / fpfd_min, 80);
+	d_min = max_t(unsigned long, DIV_ROUND_UP(fin, limits->fpfd_max), 1);
+	d_max = min_t(unsigned long, fin / limits->fpfd_min, 80);
 
 again:
-	fvco_min_fract = fvco_min << fract_shift;
-	fvco_max_fract = fvco_max << fract_shift;
+	fvco_min_fract = limits->fvco_min << fract_shift;
+	fvco_max_fract = limits->fvco_max << fract_shift;
 
 	m_min = max_t(unsigned long, DIV_ROUND_UP(fvco_min_fract, fin) * d_min, 1);
 	m_max = min_t(unsigned long, fvco_max_fract * d_max / fin, 64 << fract_shift);
@@ -319,6 +330,7 @@ static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
 	unsigned long rate, unsigned long parent_rate)
 {
 	struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
+	const struct axi_clkgen_limits *limits = &axi_clkgen->limits;
 	unsigned int d, m, dout;
 	struct axi_clkgen_div_params params;
 	uint32_t power = 0;
@@ -328,7 +340,7 @@ static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
 	if (parent_rate == 0 || rate == 0)
 		return -EINVAL;
 
-	axi_clkgen_calc_params(parent_rate, rate, &d, &m, &dout);
+	axi_clkgen_calc_params(limits, parent_rate, rate, &d, &m, &dout);
 
 	if (d == 0 || dout == 0 || m == 0)
 		return -EINVAL;
@@ -368,10 +380,12 @@ static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
 static long axi_clkgen_round_rate(struct clk_hw *hw, unsigned long rate,
 	unsigned long *parent_rate)
 {
+	struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(hw);
+	const struct axi_clkgen_limits *limits = &axi_clkgen->limits;
 	unsigned int d, m, dout;
 	unsigned long long tmp;
 
-	axi_clkgen_calc_params(*parent_rate, rate, &d, &m, &dout);
+	axi_clkgen_calc_params(limits, *parent_rate, rate, &d, &m, &dout);
 
 	if (d == 0 || dout == 0 || m == 0)
 		return -EINVAL;
@@ -527,6 +541,9 @@ static int axi_clkgen_probe(struct platform_device *pdev)
 			return -EINVAL;
 	}
 
+	memcpy(&axi_clkgen->limits, &axi_clkgen_default_limits,
+	       sizeof(axi_clkgen->limits));
+
 	clk_name = pdev->dev.of_node->name;
 	of_property_read_string(pdev->dev.of_node, "clock-output-names",
 		&clk_name);
-- 
2.17.1


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

* [PATCH v4 5/7] clk: axi-clkgen: Respect ZYNQMP PFD/VCO frequency limits
  2020-09-29 14:44 [PATCH v4 0/7] clk: axi-clk-gen: misc updates to the driver Alexandru Ardelean
                   ` (11 preceding siblings ...)
  2020-09-29 14:44 ` [PATCH v4 4/7] clk: axi-clkgen: wrap limits in a struct and keep copy on the state object Alexandru Ardelean
@ 2020-09-29 14:44 ` Alexandru Ardelean
  2020-09-29 15:30   ` Moritz Fischer
  2020-09-29 14:44 ` [PATCH v4 6/7] include: fpga: adi-axi-common.h: add definitions for supported FPGAs Alexandru Ardelean
  2020-09-29 14:44 ` [PATCH v4 7/7] clk: axi-clkgen: Add support for FPGA info Alexandru Ardelean
  14 siblings, 1 reply; 22+ messages in thread
From: Alexandru Ardelean @ 2020-09-29 14:44 UTC (permalink / raw)
  To: linux-clk, linux-fpga, linux-kernel
  Cc: mturquette, sboyd, mdf, ardeleanalex, Mathias Tausen, Alexandru Ardelean

From: Mathias Tausen <mta@gomspace.com>

Since axi-clkgen is now supported on ZYNQMP, make sure the max/min
frequencies of the PFD and VCO are respected.

Signed-off-by: Mathias Tausen <mta@gomspace.com>
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/clk/clk-axi-clkgen.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
index 4342b7735590..2319bb1c5c08 100644
--- a/drivers/clk/clk-axi-clkgen.c
+++ b/drivers/clk/clk-axi-clkgen.c
@@ -108,12 +108,21 @@ static uint32_t axi_clkgen_lookup_lock(unsigned int m)
 	return 0x1f1f00fa;
 }
 
+#ifdef ARCH_ZYNQMP
+static const struct axi_clkgen_limits axi_clkgen_default_limits = {
+	.fpfd_min = 10000,
+	.fpfd_max = 450000,
+	.fvco_min = 800000,
+	.fvco_max = 1600000,
+};
+#else
 static const struct axi_clkgen_limits axi_clkgen_default_limits = {
 	.fpfd_min = 10000,
 	.fpfd_max = 300000,
 	.fvco_min = 600000,
 	.fvco_max = 1200000,
 };
+#endif
 
 static void axi_clkgen_calc_params(const struct axi_clkgen_limits *limits,
 	unsigned long fin, unsigned long fout,
-- 
2.17.1


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

* [PATCH v4 6/7] include: fpga: adi-axi-common.h: add definitions for supported FPGAs
  2020-09-29 14:44 [PATCH v4 0/7] clk: axi-clk-gen: misc updates to the driver Alexandru Ardelean
                   ` (12 preceding siblings ...)
  2020-09-29 14:44 ` [PATCH v4 5/7] clk: axi-clkgen: Respect ZYNQMP PFD/VCO frequency limits Alexandru Ardelean
@ 2020-09-29 14:44 ` Alexandru Ardelean
  2020-09-29 14:44 ` [PATCH v4 7/7] clk: axi-clkgen: Add support for FPGA info Alexandru Ardelean
  14 siblings, 0 replies; 22+ messages in thread
From: Alexandru Ardelean @ 2020-09-29 14:44 UTC (permalink / raw)
  To: linux-clk, linux-fpga, linux-kernel
  Cc: mturquette, sboyd, mdf, ardeleanalex, Mircea Caprioru,
	Alexandru Ardelean

From: Mircea Caprioru <mircea.caprioru@analog.com>

All (newer) FPGA IP cores supported by Analog Devices, store information in
the synthesized designs. This information describes various parameters,
including the family of boards on which this is deployed, speed-grade, and
so on.

Currently, some of these definitions are deployed mostly on Xilinx boards,
but they have been considered also for FPGA boards from other vendors.

The register definitions are described at this link:
  https://wiki.analog.com/resources/fpga/docs/hdl/regmap
(the 'Base (common to all cores)' section).

Acked-by: Moritz Fischer <mdf@kernel.org>
Signed-off-by: Mircea Caprioru <mircea.caprioru@analog.com>
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 include/linux/fpga/adi-axi-common.h | 103 ++++++++++++++++++++++++++++
 1 file changed, 103 insertions(+)

diff --git a/include/linux/fpga/adi-axi-common.h b/include/linux/fpga/adi-axi-common.h
index 141ac3f251e6..1a7f18e3a384 100644
--- a/include/linux/fpga/adi-axi-common.h
+++ b/include/linux/fpga/adi-axi-common.h
@@ -13,6 +13,9 @@
 
 #define ADI_AXI_REG_VERSION			0x0000
 
+#define ADI_AXI_REG_FPGA_INFO			0x001C
+#define ADI_AXI_REG_FPGA_VOLTAGE		0x0140
+
 #define ADI_AXI_PCORE_VER(major, minor, patch)	\
 	(((major) << 16) | ((minor) << 8) | (patch))
 
@@ -20,4 +23,104 @@
 #define ADI_AXI_PCORE_VER_MINOR(version)	(((version) >> 8) & 0xff)
 #define ADI_AXI_PCORE_VER_PATCH(version)	((version) & 0xff)
 
+#define ADI_AXI_INFO_FPGA_VOLTAGE(val)		((val) & 0xffff)
+
+#define ADI_AXI_INFO_FPGA_TECH(info)		(((info) >> 24) & 0xff)
+#define ADI_AXI_INFO_FPGA_FAMILY(info)		(((info) >> 16) & 0xff)
+#define ADI_AXI_INFO_FPGA_SPEED_GRADE(info)	(((info) >> 8) & 0xff)
+#define ADI_AXI_INFO_FPGA_DEV_PACKAGE(info)	((info) & 0xff)
+
+/**
+ * FPGA Technology definitions
+ */
+#define ADI_AXI_FPGA_TECH_XILINX_UNKNOWN		0
+#define ADI_AXI_FPGA_TECH_XILINS_SERIES7		1
+#define ADI_AXI_FPGA_TECH_XILINX_ULTRASCALE		2
+#define ADI_AXI_FPGA_TECH_XILINX_ULTRASCALE_PLUS	3
+
+#define ADI_AXI_FPGA_TECH_INTEL_UNKNOWN			100
+#define ADI_AXI_FPGA_TECH_INTEL_CYCLONE_5		101
+#define ADI_AXI_FPGA_TECH_INTEL_CYCLONE_10		102
+#define ADI_AXI_FPGA_TECH_INTEL_ARRIA_10		103
+#define ADI_AXI_FPGA_TECH_INTEL_STRATIX_10		104
+
+/**
+ * FPGA Family definitions
+ */
+#define ADI_AXI_FPGA_FAMILY_UNKNOWN			0
+
+#define ADI_AXI_FPGA_FAMILY_XILINX_ARTIX		1
+#define ADI_AXI_FPGA_FAMILY_XILINX_KINTEX		2
+#define ADI_AXI_FPGA_FAMILY_XILINX_VIRTEX		3
+#define ADI_AXI_FPGA_FAMILY_XILINX_ZYNQ			4
+
+#define ADI_AXI_FPGA_FAMILY_INTEL_SX			1
+#define ADI_AXI_FPGA_FAMILY_INTEL_GX			2
+#define ADI_AXI_FPGA_FAMILY_INTEL_GT			3
+#define ADI_AXI_FPGA_FAMILY_INTEL_GZ			4
+
+/**
+ * FPGA Speed-grade definitions
+ */
+#define ADI_AXI_FPGA_SPEED_GRADE_UNKNOWN		0
+
+#define ADI_AXI_FPGA_SPEED_GRADE_XILINX_1		10
+#define ADI_AXI_FPGA_SPEED_GRADE_XILINX_1L		11
+#define ADI_AXI_FPGA_SPEED_GRADE_XILINX_1H		12
+#define ADI_AXI_FPGA_SPEED_GRADE_XILINX_1HV		13
+#define ADI_AXI_FPGA_SPEED_GRADE_XILINX_1LV		14
+#define ADI_AXI_FPGA_SPEED_GRADE_XILINX_2		20
+#define ADI_AXI_FPGA_SPEED_GRADE_XILINX_2L		21
+#define ADI_AXI_FPGA_SPEED_GRADE_XILINX_2LV		22
+#define ADI_AXI_FPGA_SPEED_GRADE_XILINX_3		30
+
+#define ADI_AXI_FPGA_SPEED_GRADE_INTEL_1		1
+#define ADI_AXI_FPGA_SPEED_GRADE_INTEL_2		2
+#define ADI_AXI_FPGA_SPEED_GRADE_INTEL_3		3
+#define ADI_AXI_FPGA_SPEED_GRADE_INTEL_4		4
+#define ADI_AXI_FPGA_SPEED_GRADE_INTEL_5		5
+#define ADI_AXI_FPGA_SPEED_GRADE_INTEL_6		6
+#define ADI_AXI_FPGA_SPEED_GRADE_INTEL_7		7
+#define ADI_AXI_FPGA_SPEED_GRADE_INTEL_8		8
+#define ADI_AXI_FPGA_SPEED_GRADE_INTEL_9		9
+
+/**
+ * FPGA Device Package definitions
+ */
+#define ADI_AXI_FPGA_DEV_PACKAGE_UNKNOWN		0
+
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_RF		1
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_FL		2
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_FF		3
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_FB		4
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_HC		5
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_FH		6
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_CS		7
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_CP		8
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_FT		9
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_FG		10
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_SB		11
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_RB		12
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_RS		13
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_CL		14
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_SF		15
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_BA		16
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_FA		17
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_FS		18
+#define ADI_AXI_FPGA_DEV_PACKAGE_XILINX_FI		19
+
+#define ADI_AXI_FPGA_DEV_PACKAGE_INTEL_BGA		1
+#define ADI_AXI_FPGA_DEV_PACKAGE_INTEL_PGA		2
+#define ADI_AXI_FPGA_DEV_PACKAGE_INTEL_FBGA		3
+#define ADI_AXI_FPGA_DEV_PACKAGE_INTEL_HBGA		4
+#define ADI_AXI_FPGA_DEV_PACKAGE_INTEL_PDIP		5
+#define ADI_AXI_FPGA_DEV_PACKAGE_INTEL_EQFP		6
+#define ADI_AXI_FPGA_DEV_PACKAGE_INTEL_PLCC		7
+#define ADI_AXI_FPGA_DEV_PACKAGE_INTEL_PQFP		8
+#define ADI_AXI_FPGA_DEV_PACKAGE_INTEL_RQFP		9
+#define ADI_AXI_FPGA_DEV_PACKAGE_INTEL_TQFP		10
+#define ADI_AXI_FPGA_DEV_PACKAGE_INTEL_UBGA		11
+#define ADI_AXI_FPGA_DEV_PACKAGE_INTEL_UFBGA		12
+#define ADI_AXI_FPGA_DEV_PACKAGE_INTEL_MBGA		13
+
 #endif /* ADI_AXI_COMMON_H_ */
-- 
2.17.1


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

* [PATCH v4 7/7] clk: axi-clkgen: Add support for FPGA info
  2020-09-29 14:44 [PATCH v4 0/7] clk: axi-clk-gen: misc updates to the driver Alexandru Ardelean
                   ` (13 preceding siblings ...)
  2020-09-29 14:44 ` [PATCH v4 6/7] include: fpga: adi-axi-common.h: add definitions for supported FPGAs Alexandru Ardelean
@ 2020-09-29 14:44 ` Alexandru Ardelean
  14 siblings, 0 replies; 22+ messages in thread
From: Alexandru Ardelean @ 2020-09-29 14:44 UTC (permalink / raw)
  To: linux-clk, linux-fpga, linux-kernel
  Cc: mturquette, sboyd, mdf, ardeleanalex, Mircea Caprioru,
	Alexandru Ardelean

From: Mircea Caprioru <mircea.caprioru@analog.com>

This patch adds support for vco maximum and minimum ranges in accordance
with fpga speed grade, voltage, device package, technology and family. This
new information is extracted from two new registers implemented in the ip
core: ADI_REG_FPGA_INFO and ADI_REG_FPGA_VOLTAGE, which are stored in the
'include/linux/fpga/adi-axi-common.h' file as they are common to all ADI
FPGA cores.

Signed-off-by: Mircea Caprioru <mircea.caprioru@analog.com>
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/clk/clk-axi-clkgen.c | 52 +++++++++++++++++++++++++++++++++++-
 1 file changed, 51 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
index 2319bb1c5c08..46fd228b0733 100644
--- a/drivers/clk/clk-axi-clkgen.c
+++ b/drivers/clk/clk-axi-clkgen.c
@@ -8,6 +8,7 @@
 
 #include <linux/platform_device.h>
 #include <linux/clk-provider.h>
+#include <linux/fpga/adi-axi-common.h>
 #include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/of.h>
@@ -242,6 +243,50 @@ static void axi_clkgen_read(struct axi_clkgen *axi_clkgen,
 	*val = readl(axi_clkgen->base + reg);
 }
 
+static void axi_clkgen_setup_ranges(struct axi_clkgen *axi_clkgen)
+{
+	struct axi_clkgen_limits *limits = &axi_clkgen->limits;
+	unsigned int reg_value;
+	unsigned int tech, family, speed_grade, voltage;
+
+	axi_clkgen_read(axi_clkgen, ADI_AXI_REG_FPGA_INFO, &reg_value);
+	tech = ADI_AXI_INFO_FPGA_TECH(reg_value);
+	family = ADI_AXI_INFO_FPGA_FAMILY(reg_value);
+	speed_grade = ADI_AXI_INFO_FPGA_SPEED_GRADE(reg_value);
+
+	axi_clkgen_read(axi_clkgen, ADI_AXI_REG_FPGA_VOLTAGE, &reg_value);
+	voltage = ADI_AXI_INFO_FPGA_VOLTAGE(reg_value);
+
+	switch (speed_grade) {
+	case ADI_AXI_FPGA_SPEED_GRADE_XILINX_1 ... ADI_AXI_FPGA_SPEED_GRADE_XILINX_1LV:
+		limits->fvco_max = 1200000;
+		limits->fpfd_max = 450000;
+		break;
+	case ADI_AXI_FPGA_SPEED_GRADE_XILINX_2 ... ADI_AXI_FPGA_SPEED_GRADE_XILINX_2LV:
+		limits->fvco_max = 1440000;
+		limits->fpfd_max = 500000;
+		if ((family == ADI_AXI_FPGA_FAMILY_XILINX_KINTEX) |
+		    (family == ADI_AXI_FPGA_FAMILY_XILINX_ARTIX)) {
+			if (voltage < 950) {
+				limits->fvco_max = 1200000;
+				limits->fpfd_max = 450000;
+			}
+		}
+		break;
+	case ADI_AXI_FPGA_SPEED_GRADE_XILINX_3:
+		limits->fvco_max = 1600000;
+		limits->fpfd_max = 550000;
+		break;
+	default:
+		break;
+	};
+
+	if (tech == ADI_AXI_FPGA_TECH_XILINX_ULTRASCALE_PLUS) {
+		limits->fvco_max = 1600000;
+		limits->fvco_min = 800000;
+	}
+}
+
 static int axi_clkgen_wait_non_busy(struct axi_clkgen *axi_clkgen)
 {
 	unsigned int timeout = 10000;
@@ -521,7 +566,7 @@ static int axi_clkgen_probe(struct platform_device *pdev)
 	const char *parent_names[2];
 	const char *clk_name;
 	struct resource *mem;
-	unsigned int i;
+	unsigned int i, ver;
 	int ret;
 
 	if (!pdev->dev.of_node)
@@ -553,6 +598,11 @@ static int axi_clkgen_probe(struct platform_device *pdev)
 	memcpy(&axi_clkgen->limits, &axi_clkgen_default_limits,
 	       sizeof(axi_clkgen->limits));
 
+	axi_clkgen_read(axi_clkgen, ADI_AXI_REG_VERSION, &ver);
+
+	if (ADI_AXI_PCORE_VER_MAJOR(ver) > 0x04)
+		axi_clkgen_setup_ranges(axi_clkgen);
+
 	clk_name = pdev->dev.of_node->name;
 	of_property_read_string(pdev->dev.of_node, "clock-output-names",
 		&clk_name);
-- 
2.17.1


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

* Re: [PATCH v4 5/7] clk: axi-clkgen: Respect ZYNQMP PFD/VCO frequency limits
  2020-09-29 14:44 ` [PATCH v4 5/7] clk: axi-clkgen: Respect ZYNQMP PFD/VCO frequency limits Alexandru Ardelean
@ 2020-09-29 15:30   ` Moritz Fischer
  2020-09-30  5:22     ` Alexandru Ardelean
  0 siblings, 1 reply; 22+ messages in thread
From: Moritz Fischer @ 2020-09-29 15:30 UTC (permalink / raw)
  To: Alexandru Ardelean
  Cc: linux-clk, linux-fpga, linux-kernel, mturquette, sboyd, mdf,
	ardeleanalex, Mathias Tausen

Hi Alexandru,

On Tue, Sep 29, 2020 at 05:44:15PM +0300, Alexandru Ardelean wrote:
> From: Mathias Tausen <mta@gomspace.com>
> 
> Since axi-clkgen is now supported on ZYNQMP, make sure the max/min
> frequencies of the PFD and VCO are respected.
> 
> Signed-off-by: Mathias Tausen <mta@gomspace.com>
> Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>

This patch still does not cover the PCIe Zynq plugged into ZynqMP linux
machine case.

> ---
>  drivers/clk/clk-axi-clkgen.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
> index 4342b7735590..2319bb1c5c08 100644
> --- a/drivers/clk/clk-axi-clkgen.c
> +++ b/drivers/clk/clk-axi-clkgen.c
> @@ -108,12 +108,21 @@ static uint32_t axi_clkgen_lookup_lock(unsigned int m)
>  	return 0x1f1f00fa;
>  }
>  
> +#ifdef ARCH_ZYNQMP
> +static const struct axi_clkgen_limits axi_clkgen_default_limits = {
> +	.fpfd_min = 10000,
> +	.fpfd_max = 450000,
> +	.fvco_min = 800000,
> +	.fvco_max = 1600000,
> +};
> +#else
>  static const struct axi_clkgen_limits axi_clkgen_default_limits = {
>  	.fpfd_min = 10000,
>  	.fpfd_max = 300000,
>  	.fvco_min = 600000,
>  	.fvco_max = 1200000,
>  };
> +#endif

I still don't understand this. You have a way to determine which fabric
you are looking at with the FPGA info. Why not:

[..] axi_clkgen_zynqmp_default_limits = {
};

[..] axi_clkgen_default_limits = {
};

Set them based on what you read back, i.e. determine which fabric you
are looking at *per clock gen* and use that info, rather than making a
compile time decision to support only one of them.

Generally speaking #ifdef $ARCH should be a last resort solution.
>  
>  static void axi_clkgen_calc_params(const struct axi_clkgen_limits *limits,
>  	unsigned long fin, unsigned long fout,
> -- 
> 2.17.1
> 

Cheers,
Moritz

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

* Re: [PATCH v4 5/7] clk: axi-clkgen: Respect ZYNQMP PFD/VCO frequency limits
  2020-09-29 15:30   ` Moritz Fischer
@ 2020-09-30  5:22     ` Alexandru Ardelean
  2020-09-30 17:16       ` Moritz Fischer
  0 siblings, 1 reply; 22+ messages in thread
From: Alexandru Ardelean @ 2020-09-30  5:22 UTC (permalink / raw)
  To: Moritz Fischer
  Cc: Alexandru Ardelean, linux-clk, linux-fpga, LKML,
	Michael Turquette, Stephen Boyd, Mathias Tausen

On Tue, Sep 29, 2020 at 6:30 PM Moritz Fischer <mdf@kernel.org> wrote:
>
> Hi Alexandru,
>
> On Tue, Sep 29, 2020 at 05:44:15PM +0300, Alexandru Ardelean wrote:
> > From: Mathias Tausen <mta@gomspace.com>
> >
> > Since axi-clkgen is now supported on ZYNQMP, make sure the max/min
> > frequencies of the PFD and VCO are respected.
> >
> > Signed-off-by: Mathias Tausen <mta@gomspace.com>
> > Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
>
> This patch still does not cover the PCIe Zynq plugged into ZynqMP linux
> machine case.
>
> > ---
> >  drivers/clk/clk-axi-clkgen.c | 9 +++++++++
> >  1 file changed, 9 insertions(+)
> >
> > diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
> > index 4342b7735590..2319bb1c5c08 100644
> > --- a/drivers/clk/clk-axi-clkgen.c
> > +++ b/drivers/clk/clk-axi-clkgen.c
> > @@ -108,12 +108,21 @@ static uint32_t axi_clkgen_lookup_lock(unsigned int m)
> >       return 0x1f1f00fa;
> >  }
> >
> > +#ifdef ARCH_ZYNQMP
> > +static const struct axi_clkgen_limits axi_clkgen_default_limits = {
> > +     .fpfd_min = 10000,
> > +     .fpfd_max = 450000,
> > +     .fvco_min = 800000,
> > +     .fvco_max = 1600000,
> > +};
> > +#else
> >  static const struct axi_clkgen_limits axi_clkgen_default_limits = {
> >       .fpfd_min = 10000,
> >       .fpfd_max = 300000,
> >       .fvco_min = 600000,
> >       .fvco_max = 1200000,
> >  };
> > +#endif
>
> I still don't understand this. You have a way to determine which fabric
> you are looking at with the FPGA info. Why not:
>
> [..] axi_clkgen_zynqmp_default_limits = {
> };
>
> [..] axi_clkgen_default_limits = {
> };
>
> Set them based on what you read back, i.e. determine which fabric you
> are looking at *per clock gen* and use that info, rather than making a
> compile time decision to support only one of them.
>
> Generally speaking #ifdef $ARCH should be a last resort solution.

The support for reading back the fabric parameters is implemented in
the AXI CLKGEN PCORE version starting with 5.0.a
Links:
https://github.com/analogdevicesinc/hdl/commits/master/library/common/up_clkgen.v
https://github.com/analogdevicesinc/hdl/commit/66823682b63c1037abdc3fc1dd4d4e63d3cfbc1a
https://github.com/analogdevicesinc/hdl/commit/7dcb2050c7946fab5ea5a273eda7c53ea7b969a6

Before that version, these details aren't there, so the best you can
do is assume compile-time ARCH defaults.

Looking at patch 7 [in this series], the axi_clkgen only updates these
defaults if the PCORE version is above version 4.x.x
https://lore.kernel.org/linux-clk/20200929144417.89816-16-alexandru.ardelean@analog.com/T/#u

Now, the question would be: do we still support PCORE versions before 5.0.a?
Depending on the answer to this question, I would be fine with the
proposed change here.

> >
> >  static void axi_clkgen_calc_params(const struct axi_clkgen_limits *limits,
> >       unsigned long fin, unsigned long fout,
> > --
> > 2.17.1
> >
>
> Cheers,
> Moritz

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

* Re: [PATCH v4 5/7] clk: axi-clkgen: Respect ZYNQMP PFD/VCO frequency limits
  2020-09-30  5:22     ` Alexandru Ardelean
@ 2020-09-30 17:16       ` Moritz Fischer
  2020-10-01  5:18         ` Alexandru Ardelean
  0 siblings, 1 reply; 22+ messages in thread
From: Moritz Fischer @ 2020-09-30 17:16 UTC (permalink / raw)
  To: Alexandru Ardelean
  Cc: Moritz Fischer, Alexandru Ardelean, linux-clk, linux-fpga, LKML,
	Michael Turquette, Stephen Boyd, Mathias Tausen

On Wed, Sep 30, 2020 at 08:22:23AM +0300, Alexandru Ardelean wrote:
> On Tue, Sep 29, 2020 at 6:30 PM Moritz Fischer <mdf@kernel.org> wrote:
> >
> > Hi Alexandru,
> >
> > On Tue, Sep 29, 2020 at 05:44:15PM +0300, Alexandru Ardelean wrote:
> > > From: Mathias Tausen <mta@gomspace.com>
> > >
> > > Since axi-clkgen is now supported on ZYNQMP, make sure the max/min
> > > frequencies of the PFD and VCO are respected.
> > >
> > > Signed-off-by: Mathias Tausen <mta@gomspace.com>
> > > Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
> >
> > This patch still does not cover the PCIe Zynq plugged into ZynqMP linux
> > machine case.
> >
> > > ---
> > >  drivers/clk/clk-axi-clkgen.c | 9 +++++++++
> > >  1 file changed, 9 insertions(+)
> > >
> > > diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
> > > index 4342b7735590..2319bb1c5c08 100644
> > > --- a/drivers/clk/clk-axi-clkgen.c
> > > +++ b/drivers/clk/clk-axi-clkgen.c
> > > @@ -108,12 +108,21 @@ static uint32_t axi_clkgen_lookup_lock(unsigned int m)
> > >       return 0x1f1f00fa;
> > >  }
> > >
> > > +#ifdef ARCH_ZYNQMP
> > > +static const struct axi_clkgen_limits axi_clkgen_default_limits = {
> > > +     .fpfd_min = 10000,
> > > +     .fpfd_max = 450000,
> > > +     .fvco_min = 800000,
> > > +     .fvco_max = 1600000,
> > > +};
> > > +#else
> > >  static const struct axi_clkgen_limits axi_clkgen_default_limits = {
> > >       .fpfd_min = 10000,
> > >       .fpfd_max = 300000,
> > >       .fvco_min = 600000,
> > >       .fvco_max = 1200000,
> > >  };
> > > +#endif
> >
> > I still don't understand this. You have a way to determine which fabric
> > you are looking at with the FPGA info. Why not:
> >
> > [..] axi_clkgen_zynqmp_default_limits = {
> > };
> >
> > [..] axi_clkgen_default_limits = {
> > };
> >
> > Set them based on what you read back, i.e. determine which fabric you
> > are looking at *per clock gen* and use that info, rather than making a
> > compile time decision to support only one of them.
> >
> > Generally speaking #ifdef $ARCH should be a last resort solution.
> 
> The support for reading back the fabric parameters is implemented in
> the AXI CLKGEN PCORE version starting with 5.0.a
> Links:
> https://github.com/analogdevicesinc/hdl/commits/master/library/common/up_clkgen.v
> https://github.com/analogdevicesinc/hdl/commit/66823682b63c1037abdc3fc1dd4d4e63d3cfbc1a
> https://github.com/analogdevicesinc/hdl/commit/7dcb2050c7946fab5ea5a273eda7c53ea7b969a6
> 
> Before that version, these details aren't there, so the best you can
> do is assume compile-time ARCH defaults.

This is a property of the instance and not of the driver. If you can't
query the hardware to figure out what you're looking at, but have
different behaviours, please use different compatible strings and make
the default limits platform data.

Something like this:

static const struct of_device_id axi_clkgen_ids[] = {
	{
		.compatible = "foo-zynqmp",
		.data = &zynqmp_default_limits,
	},
	{
		.compatible = "bar-zynq",
		.data = &zynq_default_limits,
	},

	{ },
};

And pull the info out in your probe function, then you can have both
configurations and select via device-tree.

Thanks,
Moritz

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

* Re: [PATCH v4 5/7] clk: axi-clkgen: Respect ZYNQMP PFD/VCO frequency limits
  2020-09-30 17:16       ` Moritz Fischer
@ 2020-10-01  5:18         ` Alexandru Ardelean
  2020-10-01  8:37           ` Alexandru Ardelean
  2020-10-01 19:08           ` Moritz Fischer
  0 siblings, 2 replies; 22+ messages in thread
From: Alexandru Ardelean @ 2020-10-01  5:18 UTC (permalink / raw)
  To: Moritz Fischer
  Cc: Alexandru Ardelean, linux-clk, linux-fpga, LKML,
	Michael Turquette, Stephen Boyd, Mathias Tausen

On Wed, Sep 30, 2020 at 8:16 PM Moritz Fischer <mdf@kernel.org> wrote:
>
> On Wed, Sep 30, 2020 at 08:22:23AM +0300, Alexandru Ardelean wrote:
> > On Tue, Sep 29, 2020 at 6:30 PM Moritz Fischer <mdf@kernel.org> wrote:
> > >
> > > Hi Alexandru,
> > >
> > > On Tue, Sep 29, 2020 at 05:44:15PM +0300, Alexandru Ardelean wrote:
> > > > From: Mathias Tausen <mta@gomspace.com>
> > > >
> > > > Since axi-clkgen is now supported on ZYNQMP, make sure the max/min
> > > > frequencies of the PFD and VCO are respected.
> > > >
> > > > Signed-off-by: Mathias Tausen <mta@gomspace.com>
> > > > Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
> > >
> > > This patch still does not cover the PCIe Zynq plugged into ZynqMP linux
> > > machine case.
> > >
> > > > ---
> > > >  drivers/clk/clk-axi-clkgen.c | 9 +++++++++
> > > >  1 file changed, 9 insertions(+)
> > > >
> > > > diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
> > > > index 4342b7735590..2319bb1c5c08 100644
> > > > --- a/drivers/clk/clk-axi-clkgen.c
> > > > +++ b/drivers/clk/clk-axi-clkgen.c
> > > > @@ -108,12 +108,21 @@ static uint32_t axi_clkgen_lookup_lock(unsigned int m)
> > > >       return 0x1f1f00fa;
> > > >  }
> > > >
> > > > +#ifdef ARCH_ZYNQMP
> > > > +static const struct axi_clkgen_limits axi_clkgen_default_limits = {
> > > > +     .fpfd_min = 10000,
> > > > +     .fpfd_max = 450000,
> > > > +     .fvco_min = 800000,
> > > > +     .fvco_max = 1600000,
> > > > +};
> > > > +#else
> > > >  static const struct axi_clkgen_limits axi_clkgen_default_limits = {
> > > >       .fpfd_min = 10000,
> > > >       .fpfd_max = 300000,
> > > >       .fvco_min = 600000,
> > > >       .fvco_max = 1200000,
> > > >  };
> > > > +#endif
> > >
> > > I still don't understand this. You have a way to determine which fabric
> > > you are looking at with the FPGA info. Why not:
> > >
> > > [..] axi_clkgen_zynqmp_default_limits = {
> > > };
> > >
> > > [..] axi_clkgen_default_limits = {
> > > };
> > >
> > > Set them based on what you read back, i.e. determine which fabric you
> > > are looking at *per clock gen* and use that info, rather than making a
> > > compile time decision to support only one of them.
> > >
> > > Generally speaking #ifdef $ARCH should be a last resort solution.
> >
> > The support for reading back the fabric parameters is implemented in
> > the AXI CLKGEN PCORE version starting with 5.0.a
> > Links:
> > https://github.com/analogdevicesinc/hdl/commits/master/library/common/up_clkgen.v
> > https://github.com/analogdevicesinc/hdl/commit/66823682b63c1037abdc3fc1dd4d4e63d3cfbc1a
> > https://github.com/analogdevicesinc/hdl/commit/7dcb2050c7946fab5ea5a273eda7c53ea7b969a6
> >
> > Before that version, these details aren't there, so the best you can
> > do is assume compile-time ARCH defaults.
>
> This is a property of the instance and not of the driver. If you can't
> query the hardware to figure out what you're looking at, but have
> different behaviours, please use different compatible strings and make
> the default limits platform data.
>
> Something like this:
>
> static const struct of_device_id axi_clkgen_ids[] = {
>         {
>                 .compatible = "foo-zynqmp",
>                 .data = &zynqmp_default_limits,
>         },
>         {
>                 .compatible = "bar-zynq",
>                 .data = &zynq_default_limits,
>         },
>
>         { },
> };
>

oh, apologies for not thinking about this;
i'll spin this up

thanks
Alex

> And pull the info out in your probe function, then you can have both
> configurations and select via device-tree.
>
> Thanks,
> Moritz

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

* Re: [PATCH v4 5/7] clk: axi-clkgen: Respect ZYNQMP PFD/VCO frequency limits
  2020-10-01  5:18         ` Alexandru Ardelean
@ 2020-10-01  8:37           ` Alexandru Ardelean
  2020-10-01 19:08           ` Moritz Fischer
  1 sibling, 0 replies; 22+ messages in thread
From: Alexandru Ardelean @ 2020-10-01  8:37 UTC (permalink / raw)
  To: Moritz Fischer
  Cc: Alexandru Ardelean, linux-clk, linux-fpga, LKML,
	Michael Turquette, Stephen Boyd

On Thu, Oct 1, 2020 at 8:18 AM Alexandru Ardelean
<ardeleanalex@gmail.com> wrote:
>
> On Wed, Sep 30, 2020 at 8:16 PM Moritz Fischer <mdf@kernel.org> wrote:
> >
> > On Wed, Sep 30, 2020 at 08:22:23AM +0300, Alexandru Ardelean wrote:
> > > On Tue, Sep 29, 2020 at 6:30 PM Moritz Fischer <mdf@kernel.org> wrote:
> > > >
> > > > Hi Alexandru,
> > > >
> > > > On Tue, Sep 29, 2020 at 05:44:15PM +0300, Alexandru Ardelean wrote:
> > > > > From: Mathias Tausen <mta@gomspace.com>
> > > > >
> > > > > Since axi-clkgen is now supported on ZYNQMP, make sure the max/min
> > > > > frequencies of the PFD and VCO are respected.
> > > > >
> > > > > Signed-off-by: Mathias Tausen <mta@gomspace.com>
> > > > > Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
> > > >
> > > > This patch still does not cover the PCIe Zynq plugged into ZynqMP linux
> > > > machine case.
> > > >
> > > > > ---
> > > > >  drivers/clk/clk-axi-clkgen.c | 9 +++++++++
> > > > >  1 file changed, 9 insertions(+)
> > > > >
> > > > > diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
> > > > > index 4342b7735590..2319bb1c5c08 100644
> > > > > --- a/drivers/clk/clk-axi-clkgen.c
> > > > > +++ b/drivers/clk/clk-axi-clkgen.c
> > > > > @@ -108,12 +108,21 @@ static uint32_t axi_clkgen_lookup_lock(unsigned int m)
> > > > >       return 0x1f1f00fa;
> > > > >  }
> > > > >
> > > > > +#ifdef ARCH_ZYNQMP
> > > > > +static const struct axi_clkgen_limits axi_clkgen_default_limits = {
> > > > > +     .fpfd_min = 10000,
> > > > > +     .fpfd_max = 450000,
> > > > > +     .fvco_min = 800000,
> > > > > +     .fvco_max = 1600000,
> > > > > +};
> > > > > +#else
> > > > >  static const struct axi_clkgen_limits axi_clkgen_default_limits = {
> > > > >       .fpfd_min = 10000,
> > > > >       .fpfd_max = 300000,
> > > > >       .fvco_min = 600000,
> > > > >       .fvco_max = 1200000,
> > > > >  };
> > > > > +#endif
> > > >
> > > > I still don't understand this. You have a way to determine which fabric
> > > > you are looking at with the FPGA info. Why not:
> > > >
> > > > [..] axi_clkgen_zynqmp_default_limits = {
> > > > };
> > > >
> > > > [..] axi_clkgen_default_limits = {
> > > > };
> > > >
> > > > Set them based on what you read back, i.e. determine which fabric you
> > > > are looking at *per clock gen* and use that info, rather than making a
> > > > compile time decision to support only one of them.
> > > >
> > > > Generally speaking #ifdef $ARCH should be a last resort solution.
> > >
> > > The support for reading back the fabric parameters is implemented in
> > > the AXI CLKGEN PCORE version starting with 5.0.a
> > > Links:
> > > https://github.com/analogdevicesinc/hdl/commits/master/library/common/up_clkgen.v
> > > https://github.com/analogdevicesinc/hdl/commit/66823682b63c1037abdc3fc1dd4d4e63d3cfbc1a
> > > https://github.com/analogdevicesinc/hdl/commit/7dcb2050c7946fab5ea5a273eda7c53ea7b969a6
> > >
> > > Before that version, these details aren't there, so the best you can
> > > do is assume compile-time ARCH defaults.
> >
> > This is a property of the instance and not of the driver. If you can't
> > query the hardware to figure out what you're looking at, but have
> > different behaviours, please use different compatible strings and make
> > the default limits platform data.
> >
> > Something like this:
> >
> > static const struct of_device_id axi_clkgen_ids[] = {
> >         {
> >                 .compatible = "foo-zynqmp",
> >                 .data = &zynqmp_default_limits,
> >         },
> >         {
> >                 .compatible = "bar-zynq",
> >                 .data = &zynq_default_limits,
> >         },
> >
> >         { },
> > };
> >
>
> oh, apologies for not thinking about this;
> i'll spin this up

at this point, i also need to do a device-tree binding conversion to yaml;
[which i finished just now];
so, this series has grown a bit more;

i'm thinking of splitting this series now;
i'll send the DT binding conversion first/separately;
then i'll re-send Lars' patches [for fractional dividers] separately;
they don't touch on this ZynqMP discussion;
after that, i'll resume on this part;

mind you: it's not that i am trying to avoid anyone [with this split],
but it will require Rob's review for the binding thing, and that adds
another speed to the review;
so, splitting things, will help with things going at each reviewer's rate;

>
> thanks
> Alex
>
> > And pull the info out in your probe function, then you can have both
> > configurations and select via device-tree.
> >
> > Thanks,
> > Moritz

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

* Re: [PATCH v4 5/7] clk: axi-clkgen: Respect ZYNQMP PFD/VCO frequency limits
  2020-10-01  5:18         ` Alexandru Ardelean
  2020-10-01  8:37           ` Alexandru Ardelean
@ 2020-10-01 19:08           ` Moritz Fischer
  1 sibling, 0 replies; 22+ messages in thread
From: Moritz Fischer @ 2020-10-01 19:08 UTC (permalink / raw)
  To: Alexandru Ardelean
  Cc: Moritz Fischer, Alexandru Ardelean, linux-clk, linux-fpga, LKML,
	Michael Turquette, Stephen Boyd, Mathias Tausen

On Thu, Oct 01, 2020 at 08:18:59AM +0300, Alexandru Ardelean wrote:
> On Wed, Sep 30, 2020 at 8:16 PM Moritz Fischer <mdf@kernel.org> wrote:
> >
> > On Wed, Sep 30, 2020 at 08:22:23AM +0300, Alexandru Ardelean wrote:
> > > On Tue, Sep 29, 2020 at 6:30 PM Moritz Fischer <mdf@kernel.org> wrote:
> > > >
> > > > Hi Alexandru,
> > > >
> > > > On Tue, Sep 29, 2020 at 05:44:15PM +0300, Alexandru Ardelean wrote:
> > > > > From: Mathias Tausen <mta@gomspace.com>
> > > > >
> > > > > Since axi-clkgen is now supported on ZYNQMP, make sure the max/min
> > > > > frequencies of the PFD and VCO are respected.
> > > > >
> > > > > Signed-off-by: Mathias Tausen <mta@gomspace.com>
> > > > > Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
> > > >
> > > > This patch still does not cover the PCIe Zynq plugged into ZynqMP linux
> > > > machine case.
> > > >
> > > > > ---
> > > > >  drivers/clk/clk-axi-clkgen.c | 9 +++++++++
> > > > >  1 file changed, 9 insertions(+)
> > > > >
> > > > > diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
> > > > > index 4342b7735590..2319bb1c5c08 100644
> > > > > --- a/drivers/clk/clk-axi-clkgen.c
> > > > > +++ b/drivers/clk/clk-axi-clkgen.c
> > > > > @@ -108,12 +108,21 @@ static uint32_t axi_clkgen_lookup_lock(unsigned int m)
> > > > >       return 0x1f1f00fa;
> > > > >  }
> > > > >
> > > > > +#ifdef ARCH_ZYNQMP
> > > > > +static const struct axi_clkgen_limits axi_clkgen_default_limits = {
> > > > > +     .fpfd_min = 10000,
> > > > > +     .fpfd_max = 450000,
> > > > > +     .fvco_min = 800000,
> > > > > +     .fvco_max = 1600000,
> > > > > +};
> > > > > +#else
> > > > >  static const struct axi_clkgen_limits axi_clkgen_default_limits = {
> > > > >       .fpfd_min = 10000,
> > > > >       .fpfd_max = 300000,
> > > > >       .fvco_min = 600000,
> > > > >       .fvco_max = 1200000,
> > > > >  };
> > > > > +#endif
> > > >
> > > > I still don't understand this. You have a way to determine which fabric
> > > > you are looking at with the FPGA info. Why not:
> > > >
> > > > [..] axi_clkgen_zynqmp_default_limits = {
> > > > };
> > > >
> > > > [..] axi_clkgen_default_limits = {
> > > > };
> > > >
> > > > Set them based on what you read back, i.e. determine which fabric you
> > > > are looking at *per clock gen* and use that info, rather than making a
> > > > compile time decision to support only one of them.
> > > >
> > > > Generally speaking #ifdef $ARCH should be a last resort solution.
> > >
> > > The support for reading back the fabric parameters is implemented in
> > > the AXI CLKGEN PCORE version starting with 5.0.a
> > > Links:
> > > https://github.com/analogdevicesinc/hdl/commits/master/library/common/up_clkgen.v
> > > https://github.com/analogdevicesinc/hdl/commit/66823682b63c1037abdc3fc1dd4d4e63d3cfbc1a
> > > https://github.com/analogdevicesinc/hdl/commit/7dcb2050c7946fab5ea5a273eda7c53ea7b969a6
> > >
> > > Before that version, these details aren't there, so the best you can
> > > do is assume compile-time ARCH defaults.
> >
> > This is a property of the instance and not of the driver. If you can't
> > query the hardware to figure out what you're looking at, but have
> > different behaviours, please use different compatible strings and make
> > the default limits platform data.
> >
> > Something like this:
> >
> > static const struct of_device_id axi_clkgen_ids[] = {
> >         {
> >                 .compatible = "foo-zynqmp",
> >                 .data = &zynqmp_default_limits,
> >         },
> >         {
> >                 .compatible = "bar-zynq",
> >                 .data = &zynq_default_limits,
> >         },
> >
> >         { },
> > };
> >
> 
> oh, apologies for not thinking about this;
> i'll spin this up

No worries :) 

Moritz

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

end of thread, other threads:[~2020-10-01 19:08 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-29 14:44 [PATCH v4 0/7] clk: axi-clk-gen: misc updates to the driver Alexandru Ardelean
2020-09-29 14:44 ` [PATCH v4 1/7] clk: axi-clkgen: Add support for fractional dividers Alexandru Ardelean
2020-09-29 14:44 ` [PATCH v4 2/7] clk: axi-clkgen: Set power bits for fractional mode Alexandru Ardelean
2020-09-29 14:44 ` [PATCH v4 3/7] clk: axi-clkgen: add support for ZynqMP (UltraScale) Alexandru Ardelean
2020-09-29 14:44 ` [PATCH v4 4/7] clk: axi-clkgen: wrap limits in a struct and keep copy on the state object Alexandru Ardelean
2020-09-29 14:44 ` [PATCH v4 5/7] clk: axi-clkgen: Respect ZYNQMP PFD/VCO frequency limits Alexandru Ardelean
2020-09-29 14:44 ` [PATCH v4 6/7] include: fpga: adi-axi-common.h: add definitions for supported FPGAs Alexandru Ardelean
2020-09-29 14:44 ` [PATCH v4 7/7] clk: axi-clkgen: Add support for FPGA info Alexandru Ardelean
2020-09-29 14:44 ` [PATCH v4 0/7] clk: axi-clk-gen: misc updates to the driver Alexandru Ardelean
2020-09-29 14:44 ` [PATCH v4 1/7] clk: axi-clkgen: Add support for fractional dividers Alexandru Ardelean
2020-09-29 14:44 ` [PATCH v4 2/7] clk: axi-clkgen: Set power bits for fractional mode Alexandru Ardelean
2020-09-29 14:44 ` [PATCH v4 3/7] clk: axi-clkgen: add support for ZynqMP (UltraScale) Alexandru Ardelean
2020-09-29 14:44 ` [PATCH v4 4/7] clk: axi-clkgen: wrap limits in a struct and keep copy on the state object Alexandru Ardelean
2020-09-29 14:44 ` [PATCH v4 5/7] clk: axi-clkgen: Respect ZYNQMP PFD/VCO frequency limits Alexandru Ardelean
2020-09-29 15:30   ` Moritz Fischer
2020-09-30  5:22     ` Alexandru Ardelean
2020-09-30 17:16       ` Moritz Fischer
2020-10-01  5:18         ` Alexandru Ardelean
2020-10-01  8:37           ` Alexandru Ardelean
2020-10-01 19:08           ` Moritz Fischer
2020-09-29 14:44 ` [PATCH v4 6/7] include: fpga: adi-axi-common.h: add definitions for supported FPGAs Alexandru Ardelean
2020-09-29 14:44 ` [PATCH v4 7/7] clk: axi-clkgen: Add support for FPGA info Alexandru Ardelean

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).