[PATCH 07/14] staging: clocking-wizard: Add hardware constaints

James Kelly jamespeterkelly at gmail.com
Mon May 7 01:20:33 UTC 2018


Existing constraints in the driver were overly simplistic and do not
accurately represent the diversity of Clocking Wizard IP implementations.

Constant data added to express the constraints around available
rates, divider/multiplier ratios and hardware features.  These were
extracted from the relevant Xilinx documentation. Further details on the
sources used for these constraints can be found in the driver comments.

Two device tree properties were added to choose the correct constraints
for available rates, divider/multiplier ratios and hardware features.
The default for the new "xlnx,family" property is Kintex-7 and the default
for the new "xlnx,primitive" property is MMCM.  These defaults have been
chosen to match the current driver behaviour which uses the Kintex-7 rates
for speed-grade and a number of clock outputs that corresonds to an MMCM.

Speed grade now defaults to the least restrictive (fastest) speed grade.
Speed grade is now represented within the driver as an enum to enable
possible future support of non-integer speed grades, however it has not
been implemented here to avoid breaking the existing device tree bindings.

Signed-off-by: James Kelly <jamespeterkelly at gmail.com>
---
 .../clocking-wizard/clk-xlnx-clock-wizard.c        | 307 ++++++++++++++++++---
 drivers/staging/clocking-wizard/dt-binding.txt     |  12 +-
 2 files changed, 276 insertions(+), 43 deletions(-)

diff --git a/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c b/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c
index 1dbeda92fb9a..3e670cdc072c 100644
--- a/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c
+++ b/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c
@@ -70,12 +70,179 @@
 #include <linux/err.h>
 #include <linux/regmap.h>
 
-#define WZRD_NUM_OUTPUTS	7
-#define WZRD_ACLK_MAX_FREQ	250000000UL
+#define WZRD_MAX_OUTPUTS	7
+#define KHz			1000UL
+#define MHz			1000000UL
+#define WZRD_ACLK_MAX_FREQ	(250 * MHz)
 #define WZRD_CLKNAME_AXI	"s_axi_aclk"
 #define WZRD_CLKNAME_IN1	"clk_in1"
 #define WZRD_FLAG_MULTIPLY	BIT(0)
 
+/*
+ * Clock rate constraints extracted from Xilinx data sheets listed below.
+ * The minimum rates depend on family and clock type and the maximum rates
+ * also depend on speed grade and supply voltage.
+ *
+ * At this time the driver does not support the low voltage speed grades (-xL)
+ * and it does not model the impact of supply voltage.
+ *
+ * The constraints are enforced by the common clock framework when a client
+ * issues a request to set the rate of a clock.
+ *
+ * DS181 Artix-7 FPGAs Data Sheet: DC and AC Switching Characteristics
+ * DS182 Kintex-7 FPGAs Data Sheet: DC and AC Switching Characteristics
+ * DS183 Virtex-7 T and XT FPGAs Data Sheet: DC and AC Switching Characteristics
+ * DS187 Zynq-7000 All Programmable SoC
+ *       (Z-7007S, Z-7012S, Z-7014S, Z-7010, Z-7015, and Z-7020):
+ *       DC and AC Switching Characteristics
+ * DS191 Zynq-7000 All Programmable SoC
+ *       (Z-7030, Z-7035, Z-7045, and Z-7100):
+ *       DC and AC Switching Characteristics
+ * DS892 Kintex UltraScale FPGAs Data Sheet: DC and AC Switching Characteristics
+ * DS893 Virtex UltraScale FPGAs Data Sheet: DC and AC Switching Characteristics
+ * DS922 Kintex UltraScale+ FPGAs Data Sheet:
+ *       DC and AC Switching Characteristics
+ * DS923 Virtex UltraScale+ FPGA Data Sheet: DC and AC Switching Characteristics
+ * DS925 Zynq UltraScale+ MPSoC Data Sheet: DC and AC Switching Characteristics
+ */
+
+enum clk_wzrd_rate {
+	WZRD_RATE_FIN,		// Clock wizard input frequency
+	WZRD_RATE_PFD,		// Input to phase frequency detector
+	WZRD_RATE_VCO,		// Output of voltage controlled oscillator
+	WZRD_RATE_OUT,		// Clock wizard output frequency
+	WZRD_RATE_COUNT
+};
+
+enum clk_wzrd_speed {
+	WZRD_SPEED_1,		// Speed grade 1
+	WZRD_SPEED_2,		// Speed grade 2
+	WZRD_SPEED_3,		// Speed grade 3
+	WZRD_SPEED_COUNT
+};
+
+enum clk_wzrd_family {
+	WZRD_FAMILY_ARTIX7,		// Includes low-end Zynq-7000
+	WZRD_FAMILY_KINTEX7,		// Includes Vertex-7, high-end Zynq-7000
+	WZRD_FAMILY_ULTRASCALE,		// Kintex and Vertex Ultrascale
+	WZRD_FAMILY_ULTRASCALEPLUS,	// Kintex, Vertex, Zynq Ultrascale+
+	WZRD_FAMILY_COUNT
+};
+
+static const char *clk_wzrd_family_name[WZRD_FAMILY_COUNT] = {
+	"Artix-7",
+	"Kintex-7",
+	"Ultrascale",
+	"Ultrascale+"
+};
+
+enum clk_wzrd_type {
+	WZRD_TYPE_MMCM,		// Mixed Mode Clock Manager
+	WZRD_TYPE_PLL,		// Phased Lock Loop
+	WZRD_TYPE_COUNT
+};
+
+static const char *clk_wzrd_type_name[WZRD_TYPE_COUNT] = {
+	"MMCM",
+	"PLL"
+};
+
+enum clk_wzrd_cell {
+	WZRD_CELL_MMCME2,	// 7 series MMCM
+	WZRD_CELL_PLLE2,	// 7 series PLL
+	WZRD_CELL_MMCME3,	// Ultrascale MMCM
+	WZRD_CELL_PLLE3,	// Ultrascale PLL
+	WZRD_CELL_MMCME4,	// Ultrascale+ MMCM
+	WZRD_CELL_PLLE4,	// Ultrascale+ PLL
+	WZRD_CELL_COUNT
+};
+
+struct clk_wzrd_chip {
+	enum clk_wzrd_cell	cell;
+	int			output_count;
+	unsigned long		min[WZRD_RATE_COUNT];
+	unsigned long		max[WZRD_SPEED_COUNT][WZRD_RATE_COUNT];
+};
+
+static const struct clk_wzrd_chip
+		chip_constraints[WZRD_FAMILY_COUNT][WZRD_TYPE_COUNT] = {
+	// Artix-7 DS181
+	// Zynq-7000 DS187
+	{ { .cell = WZRD_CELL_MMCME2,
+	    .output_count = 7,
+	    //            FIN        PFD         VCO         OUT
+	    .min = {    10 * MHz,  10 * MHz,  600 * MHz, 4690 * KHz },
+	    .max = { { 800 * MHz, 450 * MHz, 1200 * MHz,  800 * MHz },
+		     { 800 * MHz, 500 * MHz, 1440 * MHz,  800 * MHz },
+		     { 800 * MHz, 550 * MHz, 1600 * MHz,  800 * MHz } } },
+	  { .cell = WZRD_CELL_PLLE2,
+	    .output_count = 6,
+	    //            FIN        PFD         VCO         OUT
+	    .min = {    19 * MHz,  19 * MHz,  800 * MHz, 6250 * KHz },
+	    .max = { { 800 * MHz, 450 * MHz, 1600 * MHz,  800 * MHz },
+		     { 800 * MHz, 500 * MHz, 1866 * MHz,  800 * MHz },
+		     { 800 * MHz, 550 * MHz, 2133 * MHz,  800 * MHz } } } },
+
+	// Kintex-7 DS182
+	// Vertex-7 DS183
+	// Zynq-7000 DS191
+	{ { .cell = WZRD_CELL_MMCME2,
+	    .output_count = 7,
+	    //             FIN        PFD         VCO         OUT
+	    .min = {     10 * MHz,  10 * MHz,  600 * MHz, 4690 * KHz },
+	    .max = { {  800 * MHz, 450 * MHz, 1200 * MHz,  800 * MHz },
+		     {  933 * MHz, 500 * MHz, 1440 * MHz,  933 * MHz },
+		     { 1066 * MHz, 550 * MHz, 1600 * MHz, 1066 * MHz } } },
+	  { .cell = WZRD_CELL_PLLE2,
+	    .output_count = 6,
+	    //             FIN        PFD         VCO         OUT
+	    .min = {     19 * MHz,  19 * MHz,  800 * MHz, 6250 * KHz },
+	    .max = { {  800 * MHz, 450 * MHz, 1600 * MHz,  800 * MHz },
+		     {  933 * MHz, 500 * MHz, 1866 * MHz,  933 * MHz },
+		     { 1066 * MHz, 550 * MHz, 2133 * MHz, 1066 * MHz } } } },
+
+	// Kintex Ultrascale DS892
+	// Vertex Ultrascale DS893
+	{ { .cell = WZRD_CELL_MMCME3,
+	    .output_count = 7,
+	    //             FIN        PFD         VCO         OUT
+	    .min = {     10 * MHz,  10 * MHz,  600 * MHz, 4690 * KHz },
+	    .max = { {  800 * MHz, 450 * MHz, 1200 * MHz,  630 * MHz },
+		     {  933 * MHz, 500 * MHz, 1440 * MHz,  725 * MHz },
+		     { 1066 * MHz, 550 * MHz, 1600 * MHz,  850 * MHz } } },
+	  { .cell = WZRD_CELL_PLLE3,
+	    .output_count = 2,
+	    //             FIN           PFD         VCO         OUT
+	    .min = {     70 * MHz,     70 * MHz,  600 * MHz, 4690 * KHz },
+	    .max = { {  800 * MHz,    600 * MHz, 1200 * MHz,  630 * MHz },
+		     {  933 * MHz, 667500 * KHz, 1335 * MHz,  725 * MHz },
+		     { 1066 * MHz, 667500 * KHz, 1335 * MHz,  850 * MHz } } } },
+
+	// Kintex Ultascale+ DS922
+	// Vertex Ultrascale+ DS923
+	// Zynq Ultrascale+ DS925
+	{ { .cell = WZRD_CELL_MMCME4,
+	    .output_count = 7,
+	    //             FIN        PFD         VCO         OUT
+	    .min = {     10 * MHz,  10 * MHz,  800 * MHz, 6250 * KHz },
+	    .max = { {  800 * MHz, 450 * MHz, 1600 * MHz,  667 * MHz },
+		     {  933 * MHz, 500 * MHz, 1600 * MHz,  725 * MHz },
+		     { 1066 * MHz, 550 * MHz, 1600 * MHz,  891 * MHz } } },
+	  { .cell = WZRD_CELL_PLLE4,
+	    .output_count = 2,
+	    //             FIN           PFD         VCO         OUT
+	    .min = {     70 * MHz,     70 * MHz,  750 * MHz, 5860 * KHz },
+	    .max = { {  800 * MHz, 667500 * KHz, 1500 * MHz,  667 * MHz },
+		     {  933 * MHz, 667500 * KHz, 1500 * MHz,  725 * MHz },
+		     { 1066 * MHz, 667500 * KHz, 1500 * MHz,  891 * MHz } } } }
+};
+
+/*
+ * Clock ratio constraints extracted from Xilinx documents listed below.
+ *
+ * UG472 7 Series FPGAs Clocking Resources User Guide
+ * UG572 UltraScale Architecture Clocking Resources User Guide
+ */
 enum clk_wzrd_clk {
 	WZRD_CLK_DIV,
 	WZRD_CLK_PLL,
@@ -83,6 +250,26 @@ enum clk_wzrd_clk {
 	WZRD_CLK_COUNT
 };
 
+struct clk_wzrd_ratio {
+	u16 min;
+	u16 max;
+};
+
+static const struct clk_wzrd_ratio
+		ratio_constraints[WZRD_CELL_COUNT][WZRD_CLK_COUNT] = {
+#define ENTRY(div_min, div_max, pll_min, pll_max, out_min, out_max) \
+	{ { .min = div_min, .max = div_max }, \
+	  { .min = pll_min, .max = pll_max }, \
+	  { .min = out_min, .max = out_max } }
+	ENTRY(1, 106, 2,  64, 1, 128),	// MMCME2 UG472
+	ENTRY(1,  56, 2,  64, 1, 128),	// PLLE2 UG472
+	ENTRY(1, 106, 2,  64, 1, 128),	// MMCME3 UG572
+	ENTRY(1,  15, 1,  19, 1, 128),	// PLLE3 UG572
+	ENTRY(1, 106, 2, 128, 1, 128),	// MMCME4 UG572
+	ENTRY(1,  15, 2,  21, 1, 128)	// PLLE4 UG572
+#undef ENTRY
+};
+
 /*
  * Register map extracted from Xilinx document listed below.
  *
@@ -98,7 +285,7 @@ static const struct reg_field clk_wzrd_status_locked = REG_FIELD(0x004,  0,  0);
 static const struct reg_field clk_wzrd_divclk_divide = REG_FIELD(0x200,  0,  7);
 static const struct reg_field clk_wzrd_clkfbout_mult = REG_FIELD(0x200,  8, 15);
 static const struct reg_field clk_wzrd_clkfbout_frac = REG_FIELD(0x200, 16, 25);
-static const struct reg_field clk_wzrd_clkout_divide[WZRD_NUM_OUTPUTS] = {
+static const struct reg_field clk_wzrd_clkout_divide[WZRD_MAX_OUTPUTS] = {
 	REG_FIELD(0x208, 0, 7),
 	REG_FIELD(0x214, 0, 7),
 	REG_FIELD(0x220, 0, 7),
@@ -143,6 +330,7 @@ struct clk_wzrd_clk_data {
  * @suspended:		Flag indicating power state of the device
  * @div:		Divider internal clock provider data
  * @pll:		Phase locked loop internal clock provider data
+ * @chip:		Chip data including rate constraints
  * @clkout_data:	Array of output clock provider data
  */
 struct clk_wzrd {
@@ -151,22 +339,16 @@ struct clk_wzrd {
 	struct regmap			*regmap;
 	struct clk			*clk_in1;
 	struct clk			*axi_clk;
-	struct clk			*clkout[WZRD_NUM_OUTPUTS];
-	unsigned int			speed_grade;
+	struct clk			*clkout[WZRD_MAX_OUTPUTS];
+	enum clk_wzrd_speed		speed_grade;
 	bool				suspended;
 	struct clk_wzrd_clk_data	div_data;
 	struct clk_wzrd_clk_data	pll_data;
+	const struct clk_wzrd_chip	*chip;
 	struct clk_wzrd_clk_data	clkout_data[0];
 };
 #define to_clk_wzrd(_nb) container_of(_nb, struct clk_wzrd, nb)
 
-/* maximum frequencies for input/output clocks per speed grade */
-static const unsigned long clk_wzrd_max_freq[] = {
-	800000000UL,
-	933000000UL,
-	1066000000UL
-};
-
 static unsigned long clk_wzrd_get_ratio(struct clk_wzrd_clk_data *cwc)
 {
 	u32 int_part;
@@ -232,7 +414,7 @@ static int clk_wzrd_register_clk(struct device *dev, const char *name,
 		parent_name = clk_hw_get_name(&cw->div_data.hw);
 		break;
 	case WZRD_CLK_OUT:
-		if (instance >= WZRD_NUM_OUTPUTS) {
+		if (instance >= cw->chip->output_count) {
 			ret = -EINVAL;
 			goto err;
 		}
@@ -269,23 +451,26 @@ static int clk_wzrd_register_clk(struct device *dev, const char *name,
 static int clk_wzrd_clk_notifier(struct notifier_block *nb, unsigned long event,
 				 void *data)
 {
-	unsigned long max;
+	unsigned long min, max;
 	struct clk_notifier_data *ndata = data;
 	struct clk_wzrd *cw = to_clk_wzrd(nb);
 
 	if (cw->suspended)
 		return NOTIFY_OK;
 
-	if (ndata->clk == cw->clk_in1)
-		max = clk_wzrd_max_freq[cw->speed_grade - 1];
-	else if (ndata->clk == cw->axi_clk)
+	if (ndata->clk == cw->clk_in1) {
+		max = cw->chip->max[cw->speed_grade][WZRD_RATE_FIN];
+		min = cw->chip->min[WZRD_RATE_FIN];
+	} else if (ndata->clk == cw->axi_clk) {
 		max = WZRD_ACLK_MAX_FREQ;
-	else
+		min = 0;
+	} else {
 		return NOTIFY_DONE;	/* should never happen */
+	}
 
 	switch (event) {
 	case PRE_RATE_CHANGE:
-		if (ndata->new_rate > max)
+		if (ndata->new_rate > max || ndata->new_rate < min)
 			return NOTIFY_BAD;
 		return NOTIFY_OK;
 	case POST_RATE_CHANGE:
@@ -318,10 +503,30 @@ static SIMPLE_DEV_PM_OPS(clk_wzrd_dev_pm_ops, clk_wzrd_suspend,
 
 static int clk_wzrd_get_device_tree_data(struct device *dev)
 {
-	int num_outputs, ret;
+	int num_outputs, ret, speed_grade;
+	enum clk_wzrd_family family;
+	enum clk_wzrd_type type;
 	struct clk_wzrd *cw;
 	struct device_node *node = dev->of_node;
 
+	ret = of_property_read_u32(node, "xlnx,family", &family);
+	if (ret) {
+		dev_warn(dev, "xlnx,family not found in device tree\n");
+		family = WZRD_FAMILY_KINTEX7;
+	} else if (family >= WZRD_FAMILY_COUNT) {
+		dev_warn(dev, "Unknown xlnx,family found in device tree\n");
+		family = WZRD_FAMILY_KINTEX7;
+	}
+
+	ret = of_property_read_u32(node, "xlnx,primitive", &type);
+	if (ret) {
+		dev_warn(dev, "xlnx,primitive not found in device tree\n");
+		type = WZRD_TYPE_MMCM;
+	} else if (type >= WZRD_TYPE_COUNT) {
+		dev_warn(dev, "Unknown xlnx,primitive found in device tree\n");
+		type = WZRD_TYPE_MMCM;
+	}
+
 	num_outputs = of_property_count_strings(node,
 						"clock-output-names");
 	if (num_outputs < 1) {
@@ -331,9 +536,9 @@ static int clk_wzrd_get_device_tree_data(struct device *dev)
 		else
 			return -EINVAL;
 	}
-	if (num_outputs > WZRD_NUM_OUTPUTS) {
+	if (num_outputs > chip_constraints[family][type].output_count) {
 		dev_warn(dev, "Too many clock output names in device tree\n");
-		num_outputs = WZRD_NUM_OUTPUTS;
+		num_outputs = chip_constraints[family][type].output_count;
 	}
 
 	cw = devm_kzalloc(dev, sizeof(*cw) + num_outputs *
@@ -341,15 +546,26 @@ static int clk_wzrd_get_device_tree_data(struct device *dev)
 	if (!cw)
 		return -ENOMEM;
 	dev_set_drvdata(dev, cw);
+	cw->chip = &chip_constraints[family][type];
 	cw->clk_data.clk_num = num_outputs;
 
-	ret = of_property_read_u32(node, "speed-grade", &cw->speed_grade);
+	/*
+	 * Xilinx device tree generator puts negative values for speed grade
+	 * in the device tree.  To handle this we define speed_grade as an
+	 * int rather than unsigned and fix up the sign.  If no speed grade
+	 * is defined or the speed grade is invalid we use the least restrictive
+	 * (fastest) speed grade.
+	 */
+	cw->speed_grade = WZRD_SPEED_3;
+	ret = of_property_read_s32(node, "speed-grade", &speed_grade);
 	if (!ret) {
-		if (cw->speed_grade < 1 || cw->speed_grade > 3) {
-			dev_warn(dev, "invalid speed grade '%d'\n",
-				 cw->speed_grade);
-			cw->speed_grade = 0;
-		}
+		if (speed_grade < 0)
+			speed_grade = -speed_grade;
+
+		if (speed_grade < 1 || speed_grade > 3)
+			dev_warn(dev, "Invalid speed grade %d\n", speed_grade);
+		else
+			cw->speed_grade = speed_grade - 1;
 	}
 
 	cw->clk_in1 = devm_clk_get(dev, WZRD_CLKNAME_IN1);
@@ -358,6 +574,12 @@ static int clk_wzrd_get_device_tree_data(struct device *dev)
 			dev_err(dev, "Clock %s not found\n", WZRD_CLKNAME_IN1);
 		return PTR_ERR(cw->clk_in1);
 	}
+	ret = clk_set_rate_range(cw->clk_in1, cw->chip->min[WZRD_RATE_FIN],
+				 cw->chip->max[cw->speed_grade][WZRD_RATE_FIN]);
+	if (ret) {
+		dev_err(dev, "Unable to constrain input clock to valid range\n");
+		return ret;
+	}
 
 	cw->axi_clk = devm_clk_get(dev, WZRD_CLKNAME_AXI);
 	if (IS_ERR(cw->axi_clk)) {
@@ -367,11 +589,16 @@ static int clk_wzrd_get_device_tree_data(struct device *dev)
 	}
 	ret = clk_set_max_rate(cw->axi_clk, WZRD_ACLK_MAX_FREQ);
 	if (ret) {
-		dev_err(dev, "Unable to set clock %s to valid range\n",
+		dev_err(dev, "Unable to constrain clock %s to valid range\n",
 			WZRD_CLKNAME_AXI);
 		return ret;
 	}
 
+	dev_info(dev, "Chip Family: %s, Type: %s, Speed Grade: %d\n",
+		 clk_wzrd_family_name[family],
+		 clk_wzrd_type_name[type],
+		 cw->speed_grade + 1);
+
 	return 0;
 }
 
@@ -441,17 +668,15 @@ static int clk_wzrd_register_ccf(struct device *dev)
 	of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
 			    &cw->clk_data);
 
-	if (cw->speed_grade) {
-		cw->nb.notifier_call = clk_wzrd_clk_notifier;
+	cw->nb.notifier_call = clk_wzrd_clk_notifier;
 
-		ret = clk_notifier_register(cw->clk_in1, &cw->nb);
-			if (ret)
-				dev_warn(dev, "Unable to register input clock notifier\n");
+	ret = clk_notifier_register(cw->clk_in1, &cw->nb);
+	if (ret)
+		dev_warn(dev, "Unable to register input clock notifier\n");
 
-		ret = clk_notifier_register(cw->axi_clk, &cw->nb);
-			if (ret)
-				dev_warn(dev, "Unable to register AXI clock notifier\n");
-	}
+	ret = clk_notifier_register(cw->axi_clk, &cw->nb);
+	if (ret)
+		dev_warn(dev, "Unable to register AXI clock notifier\n");
 
 	ret = 0;
 
@@ -489,10 +714,8 @@ static int clk_wzrd_remove(struct platform_device *pdev)
 
 	of_clk_del_provider(pdev->dev.of_node);
 
-	if (cw->speed_grade) {
-		clk_notifier_unregister(cw->axi_clk, &cw->nb);
-		clk_notifier_unregister(cw->clk_in1, &cw->nb);
-	}
+	clk_notifier_unregister(cw->axi_clk, &cw->nb);
+	clk_notifier_unregister(cw->clk_in1, &cw->nb);
 
 	return 0;
 }
diff --git a/drivers/staging/clocking-wizard/dt-binding.txt b/drivers/staging/clocking-wizard/dt-binding.txt
index 723271e93316..6e7859a6e751 100644
--- a/drivers/staging/clocking-wizard/dt-binding.txt
+++ b/drivers/staging/clocking-wizard/dt-binding.txt
@@ -15,7 +15,15 @@ Required properties:
  - clock-output-names: Names for the output clocks
 
 Optional properties:
- - speed-grade: Speed grade of the device (valid values are 1..3)
+ - speed-grade: Speed grade of the device. Valid values are 1..3, default is 3
+ - xlnx,family: Device family
+	0 - Artix-7 and low-end Zynq-7000
+	1 - Kintex-7, Vertex-7 and high-end Zynq-7000 (default)
+	2 - Kintex, Vertex Ultrascale
+	3 - Kintex, Vertex, Zynq Ultrascale+
+ - xlnx,primitive: Clocking Wizard primitive
+	0 - MMCM (default)
+	1 - PLL
 
 Example:
 	clock-generator at 40040000 {
@@ -27,4 +35,6 @@ Example:
 		clock-output-names = "clk_out0", "clk_out1", "clk_out2",
 				     "clk_out3", "clk_out4", "clk_out5",
 				     "clk_out6", "clk_out7";
+		xlnx,family = <0>;
+		xlnx,primitive = <0>;
 	};
-- 
2.15.1 (Apple Git-101)



More information about the devel mailing list