[PATCH 1/8] CLK: ARC: HSDK: avoid code duplication

Eugeniy Paltsev Eugeniy.Paltsev at synopsys.com
Fri May 8 14:44:13 CEST 2020


hsdk_axi_clk_cfg and hsdk_tun_clk_cfg clock divider structures
and functions for their processing are almost the same so
merge them to avoid code duplication.

Signed-off-by: Eugeniy Paltsev <Eugeniy.Paltsev at synopsys.com>
---
 drivers/clk/clk-hsdk-cgu.c | 112 +++++++++++++------------------------
 1 file changed, 40 insertions(+), 72 deletions(-)

diff --git a/drivers/clk/clk-hsdk-cgu.c b/drivers/clk/clk-hsdk-cgu.c
index 3035c5fb38e..a51e78071a9 100644
--- a/drivers/clk/clk-hsdk-cgu.c
+++ b/drivers/clk/clk-hsdk-cgu.c
@@ -126,45 +126,31 @@
 #define PARENT_RATE_27			27000000 /* fixed clock - xtal */
 #define CGU_MAX_CLOCKS			27
 
-#define CGU_SYS_CLOCKS			16
-#define MAX_AXI_CLOCKS			4
+#define MAX_FREQ_VARIATIONS		6
 
-#define CGU_TUN_CLOCKS			4
-#define MAX_TUN_CLOCKS			6
-
-struct hsdk_tun_idiv_cfg {
+struct hsdk_idiv_cfg {
 	u32 oft;
-	u8  val[MAX_TUN_CLOCKS];
+	u8  val[MAX_FREQ_VARIATIONS];
 };
 
-struct hsdk_tun_clk_cfg {
-	const u32 clk_rate[MAX_TUN_CLOCKS];
-	const u32 pll_rate[MAX_TUN_CLOCKS];
-	const struct hsdk_tun_idiv_cfg idiv[CGU_TUN_CLOCKS];
+struct hsdk_div_full_cfg {
+	const u32 clk_rate[MAX_FREQ_VARIATIONS];
+	const u32 pll_rate[MAX_FREQ_VARIATIONS];
+	const struct hsdk_idiv_cfg idiv[];
 };
 
-static const struct hsdk_tun_clk_cfg tun_clk_cfg = {
+static const struct hsdk_div_full_cfg tun_clk_cfg = {
 	{ 25000000,  50000000,  75000000,  100000000, 125000000, 150000000 },
 	{ 600000000, 600000000, 600000000, 600000000, 750000000, 600000000 }, {
 	{ CGU_TUN_IDIV_TUN,	{ 24,	12,	8,	6,	6,	4 } },
 	{ CGU_TUN_IDIV_ROM,	{ 4,	4,	4,	4,	5,	4 } },
 	{ CGU_TUN_IDIV_PWM,	{ 8,	8,	8,	8,	10,	8 } },
-	{ CGU_TUN_IDIV_TIMER,	{ 12,	12,	12,	12,	15,	12 } }
+	{ CGU_TUN_IDIV_TIMER,	{ 12,	12,	12,	12,	15,	12 } },
+	{ /* last one */ }
 	}
 };
 
-struct hsdk_sys_idiv_cfg {
-	u32 oft;
-	u8  val[MAX_AXI_CLOCKS];
-};
-
-struct hsdk_axi_clk_cfg {
-	const u32 clk_rate[MAX_AXI_CLOCKS];
-	const u32 pll_rate[MAX_AXI_CLOCKS];
-	const struct hsdk_sys_idiv_cfg idiv[CGU_SYS_CLOCKS];
-};
-
-static const struct hsdk_axi_clk_cfg axi_clk_cfg = {
+static const struct hsdk_div_full_cfg axi_clk_cfg = {
 	{ 200000000,	400000000,	600000000,	800000000 },
 	{ 800000000,	800000000,	600000000,	800000000 }, {
 	{ CGU_SYS_IDIV_APB,	 { 4,	4,	3,	4 } },	/* APB */
@@ -182,7 +168,8 @@ static const struct hsdk_axi_clk_cfg axi_clk_cfg = {
 	{ CGU_SYS_IDIV_SPI_REF,	 { 24,	24,	18,	24 } },	/* SPI-REF */
 	{ CGU_SYS_IDIV_I2C_REF,	 { 4,	4,	3,	4 } },	/* I2C-REF */
 	{ CGU_SYS_IDIV_UART_REF, { 24,	24,	18,	24 } },	/* UART-REF */
-	{ CGU_SYS_IDIV_EBI_REF,	 { 16,	16,	12,	16 } }	/* EBI-REF */
+	{ CGU_SYS_IDIV_EBI_REF,	 { 16,	16,	12,	16 } },	/* EBI-REF */
+	{ /* last one */ }
 	}
 };
 
@@ -546,8 +533,13 @@ static ulong cpu_clk_set(struct clk *sclk, ulong rate)
 	return ret;
 }
 
-/* Special behavior: wen we set this clock we set both idiv and pll and all pll dividers */
-static ulong axi_clk_set(struct clk *sclk, ulong rate)
+/*
+ * Special behavior:
+ * when we set these clocks we set both PLL and all idiv dividers related to
+ * this PLL domain.
+ */
+static ulong common_div_clk_set(struct clk *sclk, ulong rate,
+				const struct hsdk_div_full_cfg *cfg)
 {
 	struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev);
 	ulong pll_rate;
@@ -556,71 +548,47 @@ static ulong axi_clk_set(struct clk *sclk, ulong rate)
 
 	pll_rate = pll_get(sclk);
 
-	for (i = 0; i < MAX_AXI_CLOCKS; i++) {
-		if (axi_clk_cfg.clk_rate[i] == rate) {
+	for (i = 0; i < MAX_FREQ_VARIATIONS; i++) {
+		/* unused freq variations are filled with 0 */
+		if (!cfg->clk_rate[i])
+			break;
+
+		if (cfg->clk_rate[i] == rate) {
 			freq_idx = i;
 			break;
 		}
 	}
 
 	if (freq_idx < 0) {
-		pr_err("axi clk: invalid rate=%ld Hz\n", rate);
+		pr_err("clk: invalid rate=%ld Hz\n", rate);
 		return -EINVAL;
 	}
 
 	/* configure PLL before dividers */
-	if (axi_clk_cfg.pll_rate[freq_idx] < pll_rate)
-		ret = pll_set(sclk, axi_clk_cfg.pll_rate[freq_idx]);
+	if (cfg->pll_rate[freq_idx] < pll_rate)
+		ret = pll_set(sclk, cfg->pll_rate[freq_idx]);
 
 	/* configure SYS dividers */
-	for (i = 0; i < CGU_SYS_CLOCKS; i++) {
-		clk->idiv_regs = clk->cgu_regs + axi_clk_cfg.idiv[i].oft;
-		hsdk_idiv_write(clk, axi_clk_cfg.idiv[i].val[freq_idx]);
+	for (i = 0; cfg->idiv[i].oft != 0; i++) {
+		clk->idiv_regs = clk->cgu_regs + cfg->idiv[i].oft;
+		hsdk_idiv_write(clk, cfg->idiv[i].val[freq_idx]);
 	}
 
 	/* configure PLL after dividers */
-	if (axi_clk_cfg.pll_rate[freq_idx] >= pll_rate)
-		ret = pll_set(sclk, axi_clk_cfg.pll_rate[freq_idx]);
+	if (cfg->pll_rate[freq_idx] >= pll_rate)
+		ret = pll_set(sclk, cfg->pll_rate[freq_idx]);
 
 	return ret;
 }
 
-static ulong tun_clk_set(struct clk *sclk, ulong rate)
+static ulong axi_clk_set(struct clk *sclk, ulong rate)
 {
-	struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev);
-	ulong pll_rate;
-	int i, freq_idx = -1;
-	ulong ret = 0;
-
-	pll_rate = pll_get(sclk);
-
-	for (i = 0; i < MAX_TUN_CLOCKS; i++) {
-		if (tun_clk_cfg.clk_rate[i] == rate) {
-			freq_idx = i;
-			break;
-		}
-	}
-
-	if (freq_idx < 0) {
-		pr_err("tun clk: invalid rate=%ld Hz\n", rate);
-		return -EINVAL;
-	}
-
-	/* configure PLL before dividers */
-	if (tun_clk_cfg.pll_rate[freq_idx] < pll_rate)
-		ret = pll_set(sclk, tun_clk_cfg.pll_rate[freq_idx]);
-
-	/* configure SYS dividers */
-	for (i = 0; i < CGU_TUN_CLOCKS; i++) {
-		clk->idiv_regs = clk->cgu_regs + tun_clk_cfg.idiv[i].oft;
-		hsdk_idiv_write(clk, tun_clk_cfg.idiv[i].val[freq_idx]);
-	}
-
-	/* configure PLL after dividers */
-	if (tun_clk_cfg.pll_rate[freq_idx] >= pll_rate)
-		ret = pll_set(sclk, tun_clk_cfg.pll_rate[freq_idx]);
+	return common_div_clk_set(sclk, rate, &axi_clk_cfg);
+}
 
-	return ret;
+static ulong tun_clk_set(struct clk *sclk, ulong rate)
+{
+	return common_div_clk_set(sclk, rate, &tun_clk_cfg);
 }
 
 static ulong idiv_set(struct clk *sclk, ulong rate)
-- 
2.21.3



More information about the U-Boot mailing list