All of lore.kernel.org
 help / color / mirror / Atom feed
* [RESEND PATCH 1/2] clk: axi-clkgen: wrap limits in a struct and keep copy on the state object
@ 2020-12-03  7:40 Alexandru Ardelean
  2020-12-03  7:40 ` [RESEND PATCH 2/2] clk: axi-clkgen: move the OF table at the bottom of the file Alexandru Ardelean
  2020-12-17  9:53 ` [RESEND PATCH 1/2] clk: axi-clkgen: wrap limits in a struct and keep copy on the state object Stephen Boyd
  0 siblings, 2 replies; 4+ messages in thread
From: Alexandru Ardelean @ 2020-12-03  7:40 UTC (permalink / raw)
  To: linux-clk, linux-kernel
  Cc: sboyd, mturquette, mdf, lars, 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 (or some other inter-connect, and then these
limits need to be adjusted for each instance of the AXI CLKGEN.

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.

The limits are stored on the device-tree OF table, so that we can adjust
them via the compatible string.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---

Initial send:
  https://lore.kernel.org/linux-clk/20201019111809.56374-1-alexandru.ardelean@analog.com/

 drivers/clk/clk-axi-clkgen.c | 48 +++++++++++++++++++++++-------------
 1 file changed, 31 insertions(+), 17 deletions(-)

diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
index 14d803e6af62..963a62e9c728 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_zynq_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;
@@ -485,6 +499,7 @@ static const struct clk_ops axi_clkgen_ops = {
 static const struct of_device_id axi_clkgen_ids[] = {
 	{
 		.compatible = "adi,axi-clkgen-2.00.a",
+		.data = &axi_clkgen_zynq_default_limits,
 	},
 	{ },
 };
@@ -492,7 +507,7 @@ MODULE_DEVICE_TABLE(of, axi_clkgen_ids);
 
 static int axi_clkgen_probe(struct platform_device *pdev)
 {
-	const struct of_device_id *id;
+	const struct axi_clkgen_limits *dflt_limits;
 	struct axi_clkgen *axi_clkgen;
 	struct clk_init_data init;
 	const char *parent_names[2];
@@ -501,11 +516,8 @@ static int axi_clkgen_probe(struct platform_device *pdev)
 	unsigned int i;
 	int ret;
 
-	if (!pdev->dev.of_node)
-		return -ENODEV;
-
-	id = of_match_node(axi_clkgen_ids, pdev->dev.of_node);
-	if (!id)
+	dflt_limits = device_get_match_data(&pdev->dev);
+	if (!dflt_limits)
 		return -ENODEV;
 
 	axi_clkgen = devm_kzalloc(&pdev->dev, sizeof(*axi_clkgen), GFP_KERNEL);
@@ -527,6 +539,8 @@ static int axi_clkgen_probe(struct platform_device *pdev)
 			return -EINVAL;
 	}
 
+	memcpy(&axi_clkgen->limits, dflt_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.27.0


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

* [RESEND PATCH 2/2] clk: axi-clkgen: move the OF table at the bottom of the file
  2020-12-03  7:40 [RESEND PATCH 1/2] clk: axi-clkgen: wrap limits in a struct and keep copy on the state object Alexandru Ardelean
@ 2020-12-03  7:40 ` Alexandru Ardelean
  2020-12-17  9:53   ` Stephen Boyd
  2020-12-17  9:53 ` [RESEND PATCH 1/2] clk: axi-clkgen: wrap limits in a struct and keep copy on the state object Stephen Boyd
  1 sibling, 1 reply; 4+ messages in thread
From: Alexandru Ardelean @ 2020-12-03  7:40 UTC (permalink / raw)
  To: linux-clk, linux-kernel
  Cc: sboyd, mturquette, mdf, lars, ardeleanalex, Alexandru Ardelean

The change is mostly cosmetic. No functional changes.
Since the driver now uses of_device_get_match_data() to obtain some driver
specific info, there is no need to define the OF table before the probe
function.

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

diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
index 963a62e9c728..ad86e031ba3e 100644
--- a/drivers/clk/clk-axi-clkgen.c
+++ b/drivers/clk/clk-axi-clkgen.c
@@ -496,15 +496,6 @@ static const struct clk_ops axi_clkgen_ops = {
 	.get_parent = axi_clkgen_get_parent,
 };
 
-static const struct of_device_id axi_clkgen_ids[] = {
-	{
-		.compatible = "adi,axi-clkgen-2.00.a",
-		.data = &axi_clkgen_zynq_default_limits,
-	},
-	{ },
-};
-MODULE_DEVICE_TABLE(of, axi_clkgen_ids);
-
 static int axi_clkgen_probe(struct platform_device *pdev)
 {
 	const struct axi_clkgen_limits *dflt_limits;
@@ -568,6 +559,15 @@ static int axi_clkgen_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct of_device_id axi_clkgen_ids[] = {
+	{
+		.compatible = "adi,axi-clkgen-2.00.a",
+		.data = &axi_clkgen_zynq_default_limits,
+	},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, axi_clkgen_ids);
+
 static struct platform_driver axi_clkgen_driver = {
 	.driver = {
 		.name = "adi-axi-clkgen",
-- 
2.27.0


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

* Re: [RESEND PATCH 1/2] clk: axi-clkgen: wrap limits in a struct and keep copy on the state object
  2020-12-03  7:40 [RESEND PATCH 1/2] clk: axi-clkgen: wrap limits in a struct and keep copy on the state object Alexandru Ardelean
  2020-12-03  7:40 ` [RESEND PATCH 2/2] clk: axi-clkgen: move the OF table at the bottom of the file Alexandru Ardelean
@ 2020-12-17  9:53 ` Stephen Boyd
  1 sibling, 0 replies; 4+ messages in thread
From: Stephen Boyd @ 2020-12-17  9:53 UTC (permalink / raw)
  To: Alexandru Ardelean, linux-clk, linux-kernel
  Cc: mturquette, mdf, lars, ardeleanalex, Alexandru Ardelean

Quoting Alexandru Ardelean (2020-12-02 23:40:36)
> 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 (or some other inter-connect, and then these
> limits need to be adjusted for each instance of the AXI CLKGEN.
> 
> 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.
> 
> The limits are stored on the device-tree OF table, so that we can adjust
> them via the compatible string.
> 
> Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
> ---

Applied to clk-next

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

* Re: [RESEND PATCH 2/2] clk: axi-clkgen: move the OF table at the bottom of the file
  2020-12-03  7:40 ` [RESEND PATCH 2/2] clk: axi-clkgen: move the OF table at the bottom of the file Alexandru Ardelean
@ 2020-12-17  9:53   ` Stephen Boyd
  0 siblings, 0 replies; 4+ messages in thread
From: Stephen Boyd @ 2020-12-17  9:53 UTC (permalink / raw)
  To: Alexandru Ardelean, linux-clk, linux-kernel
  Cc: mturquette, mdf, lars, ardeleanalex, Alexandru Ardelean

Quoting Alexandru Ardelean (2020-12-02 23:40:37)
> The change is mostly cosmetic. No functional changes.
> Since the driver now uses of_device_get_match_data() to obtain some driver
> specific info, there is no need to define the OF table before the probe
> function.
> 
> Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
> ---

Applied to clk-next

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

end of thread, other threads:[~2020-12-17  9:54 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-03  7:40 [RESEND PATCH 1/2] clk: axi-clkgen: wrap limits in a struct and keep copy on the state object Alexandru Ardelean
2020-12-03  7:40 ` [RESEND PATCH 2/2] clk: axi-clkgen: move the OF table at the bottom of the file Alexandru Ardelean
2020-12-17  9:53   ` Stephen Boyd
2020-12-17  9:53 ` [RESEND PATCH 1/2] clk: axi-clkgen: wrap limits in a struct and keep copy on the state object Stephen Boyd

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.