Linux-Clk Archive on lore.kernel.org
 help / Atom feed
* [PATCH 0/3] Enhance loongson-1 clock driver
@ 2019-01-25 13:34 Jiaxun Yang
  2019-01-25 13:34 ` [PATCH 1/3] clk: loongson1: add configuration option for loongson1 clks Jiaxun Yang
                   ` (3 more replies)
  0 siblings, 4 replies; 16+ messages in thread
From: Jiaxun Yang @ 2019-01-25 13:34 UTC (permalink / raw)
  To: linux-mips
  Cc: mturquette, sboyd, linux-clk, linux-kernel, robh+dt,
	mark.rutland, devicetree

Add of support for ls1c-clock and ls1b-clock



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

* [PATCH 1/3] clk: loongson1: add configuration option for loongson1 clks
  2019-01-25 13:34 [PATCH 0/3] Enhance loongson-1 clock driver Jiaxun Yang
@ 2019-01-25 13:34 ` Jiaxun Yang
  2019-01-25 13:34 ` [PATCH 2/3] clk: loongson1: add of support Jiaxun Yang
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 16+ messages in thread
From: Jiaxun Yang @ 2019-01-25 13:34 UTC (permalink / raw)
  To: linux-mips
  Cc: mturquette, sboyd, linux-clk, linux-kernel, robh+dt,
	mark.rutland, devicetree, Jiaxun Yang

The patch introduces options for loongson1 clocks so we can
select the driver we need.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 drivers/clk/Kconfig            |  1 +
 drivers/clk/Makefile           |  2 +-
 drivers/clk/loongson1/Kconfig  | 27 +++++++++++++++++++++++++++
 drivers/clk/loongson1/Makefile |  7 ++++---
 4 files changed, 33 insertions(+), 4 deletions(-)
 create mode 100644 drivers/clk/loongson1/Kconfig

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index e5b2fe80eab4..136d3d73c6df 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -298,6 +298,7 @@ source "drivers/clk/imgtec/Kconfig"
 source "drivers/clk/imx/Kconfig"
 source "drivers/clk/ingenic/Kconfig"
 source "drivers/clk/keystone/Kconfig"
+source "drivers/clk/loongson1/Kconfig"
 source "drivers/clk/mediatek/Kconfig"
 source "drivers/clk/meson/Kconfig"
 source "drivers/clk/mvebu/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 8a9440a97500..7d29e545caf0 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -76,7 +76,7 @@ obj-y					+= imx/
 obj-y					+= ingenic/
 obj-$(CONFIG_ARCH_K3)			+= keystone/
 obj-$(CONFIG_ARCH_KEYSTONE)		+= keystone/
-obj-$(CONFIG_MACH_LOONGSON32)		+= loongson1/
+obj-y					+= loongson1/
 obj-y					+= mediatek/
 obj-$(CONFIG_COMMON_CLK_AMLOGIC)	+= meson/
 obj-$(CONFIG_MACH_PIC32)		+= microchip/
diff --git a/drivers/clk/loongson1/Kconfig b/drivers/clk/loongson1/Kconfig
new file mode 100644
index 000000000000..e2220332d797
--- /dev/null
+++ b/drivers/clk/loongson1/Kconfig
@@ -0,0 +1,27 @@
+menu "Loongson-1 Clock drivers"
+	depends on MACH_LOONGSON32
+
+config LOONGSON1_CLOCK_COMMON
+	bool
+
+config LOONGSON1_CLOCK_LS1B
+	bool "Loongson 1B driver"
+	default y
+	select LOONGSON1_CLOCK_COMMON
+	help
+	  Support the clocks provided by the clock hardware on Loongson-1B
+	  and compatible SoCs.
+
+	  If building for a Loongson-1B SoC, you want to say Y here.
+
+config LOONGSON1_CLOCK_LS1C
+	bool "Loongson 1C driver"
+	default y
+	select LOONGSON1_CLOCK_COMMON
+	help
+	  Support the clocks provided by the clock hardware on Loongson-1C
+	  and compatible SoCs.
+
+	  If building for a Loongson-1C SoC, you want to say Y here.
+
+endmenu
diff --git a/drivers/clk/loongson1/Makefile b/drivers/clk/loongson1/Makefile
index b7f6a16390e0..9240189183ff 100644
--- a/drivers/clk/loongson1/Makefile
+++ b/drivers/clk/loongson1/Makefile
@@ -1,3 +1,4 @@
-obj-y				+= clk.o
-obj-$(CONFIG_LOONGSON1_LS1B)	+= clk-loongson1b.o
-obj-$(CONFIG_LOONGSON1_LS1C)	+= clk-loongson1c.o
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_LOONGSON1_CLOCK_COMMON)	+= clk.o
+obj-$(CONFIG_LOONGSON1_CLOCK_LS1B)	+= clk-loongson1b.o
+obj-$(CONFIG_LOONGSON1_CLOCK_LS1C)	+= clk-loongson1c.o
-- 
2.20.1


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

* [PATCH 2/3] clk: loongson1: add of support
  2019-01-25 13:34 [PATCH 0/3] Enhance loongson-1 clock driver Jiaxun Yang
  2019-01-25 13:34 ` [PATCH 1/3] clk: loongson1: add configuration option for loongson1 clks Jiaxun Yang
@ 2019-01-25 13:34 ` Jiaxun Yang
  2019-01-25 13:34 ` [PATCH 3/3] dt-bindings: clock: Add loongson-1 clock bindings Jiaxun Yang
  2019-01-28 15:20 ` [PATCH 0/3] Enhance loongson-1 clock driver Jiaxun Yang
  3 siblings, 0 replies; 16+ messages in thread
From: Jiaxun Yang @ 2019-01-25 13:34 UTC (permalink / raw)
  To: linux-mips
  Cc: mturquette, sboyd, linux-clk, linux-kernel, robh+dt,
	mark.rutland, devicetree, Jiaxun Yang

This patch add of support by split the clk_hw register and
clkdev register, then handle the of clk_hw via
of_clk_hw_onecell_get.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 drivers/clk/loongson1/clk-loongson1b.c | 176 +++++++++++++++++++------
 drivers/clk/loongson1/clk-loongson1c.c | 144 +++++++++++++++-----
 drivers/clk/loongson1/clk.c            |  92 ++++++++++++-
 drivers/clk/loongson1/clk.h            |  18 ++-
 4 files changed, 347 insertions(+), 83 deletions(-)

diff --git a/drivers/clk/loongson1/clk-loongson1b.c b/drivers/clk/loongson1/clk-loongson1b.c
index f36a97e993c0..47f8d4ae2544 100644
--- a/drivers/clk/loongson1/clk-loongson1b.c
+++ b/drivers/clk/loongson1/clk-loongson1b.c
@@ -1,10 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2012-2016 Zhang, Keguang <keguang.zhang@gmail.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
+ * Copyright (c) 2019 Jiaxun Yang <jiaxun.yang@flygoat.com>
  */
 
 #include <linux/clkdev.h>
@@ -12,11 +9,41 @@
 #include <linux/io.h>
 #include <linux/err.h>
 
-#include <loongson1.h>
 #include "clk.h"
+#include <dt-bindings/clock/ls1b-clock.h>
+
+#define LS1B_CLK_COUNT	9
 
-#define OSC		(33 * 1000000)
 #define DIV_APB		2
+/* Clock PLL Divisor Register Bits */
+#define DIV_DC_EN			BIT(31)
+#define DIV_DC_RST			BIT(30)
+#define DIV_CPU_EN			BIT(25)
+#define DIV_CPU_RST			BIT(24)
+#define DIV_DDR_EN			BIT(19)
+#define DIV_DDR_RST			BIT(18)
+#define RST_DC_EN			BIT(5)
+#define RST_DC				BIT(4)
+#define RST_DDR_EN			BIT(3)
+#define RST_DDR				BIT(2)
+#define RST_CPU_EN			BIT(1)
+#define RST_CPU				BIT(0)
+
+#define DIV_DC_SHIFT			26
+#define DIV_CPU_SHIFT			20
+#define DIV_DDR_SHIFT			14
+
+#define DIV_DC_WIDTH			4
+#define DIV_CPU_WIDTH			4
+#define DIV_DDR_WIDTH			4
+
+#define BYPASS_DC_SHIFT			12
+#define BYPASS_DDR_SHIFT		10
+#define BYPASS_CPU_SHIFT		8
+
+#define BYPASS_DC_WIDTH			1
+#define BYPASS_DDR_WIDTH		1
+#define BYPASS_CPU_WIDTH		1
 
 static DEFINE_SPINLOCK(_lock);
 
@@ -25,9 +52,9 @@ static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw,
 {
 	u32 pll, rate;
 
-	pll = __raw_readl(LS1X_CLK_PLL_FREQ);
+	pll = __raw_readl(CLK_PLL_FREQ_ADDR);
 	rate = 12 + (pll & GENMASK(5, 0));
-	rate *= OSC;
+	rate *= parent_rate;
 	rate >>= 1;
 
 	return rate;
@@ -37,21 +64,29 @@ static const struct clk_ops ls1x_pll_clk_ops = {
 	.recalc_rate = ls1x_pll_recalc_rate,
 };
 
-static const char *const cpu_parents[] = { "cpu_clk_div", "osc_clk", };
-static const char *const ahb_parents[] = { "ahb_clk_div", "osc_clk", };
-static const char *const dc_parents[] = { "dc_clk_div", "osc_clk", };
 
-void __init ls1x_clk_init(void)
+struct clk_hw_onecell_data __init *ls1b_clk_init_hw(const char *osc_name)
 {
 	struct clk_hw *hw;
+	struct clk_hw_onecell_data *onecell;
+	const char *parents[2];
+
+	onecell = kzalloc(sizeof(*onecell) +
+			  (LS1B_CLK_COUNT * sizeof(struct clk_hw *)),
+			  GFP_KERNEL);
+
+	if (!onecell)
+		return NULL;
 
-	hw = clk_hw_register_fixed_rate(NULL, "osc_clk", NULL, 0, OSC);
-	clk_hw_register_clkdev(hw, "osc_clk", NULL);
+	onecell->num = LS1B_CLK_COUNT;
 
+	parents[1] = osc_name;
 	/* clock derived from 33 MHz OSC clk */
-	hw = clk_hw_register_pll(NULL, "pll_clk", "osc_clk",
+	hw = clk_hw_register_pll(NULL, "pll_clk", osc_name,
 				 &ls1x_pll_clk_ops, 0);
-	clk_hw_register_clkdev(hw, "pll_clk", NULL);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1B_CLK_PLL] = hw;
 
 	/* clock derived from PLL clk */
 	/*                                 _____
@@ -61,16 +96,22 @@ void __init ls1x_clk_init(void)
 	 *                                |_____|
 	 */
 	hw = clk_hw_register_divider(NULL, "cpu_clk_div", "pll_clk",
-				   CLK_GET_RATE_NOCACHE, LS1X_CLK_PLL_DIV,
+				   CLK_GET_RATE_NOCACHE, CLK_PLL_DIV_ADDR,
 				   DIV_CPU_SHIFT, DIV_CPU_WIDTH,
 				   CLK_DIVIDER_ONE_BASED |
 				   CLK_DIVIDER_ROUND_CLOSEST, &_lock);
-	clk_hw_register_clkdev(hw, "cpu_clk_div", NULL);
-	hw = clk_hw_register_mux(NULL, "cpu_clk", cpu_parents,
-			       ARRAY_SIZE(cpu_parents),
-			       CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV,
+	if (!hw)
+		goto err;
+	onecell->hws[LS1B_CLK_CPU_DIV] = hw;
+
+	parents[0] = "cpu_clk_div";
+	hw = clk_hw_register_mux(NULL, "cpu_clk", parents,
+			       ARRAY_SIZE(parents),
+			       CLK_SET_RATE_NO_REPARENT, CLK_PLL_DIV_ADDR,
 			       BYPASS_CPU_SHIFT, BYPASS_CPU_WIDTH, 0, &_lock);
-	clk_hw_register_clkdev(hw, "cpu_clk", NULL);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1B_CLK_CPU] = hw;
 
 	/*                                 _____
 	 *         _______________________|     |
@@ -79,14 +120,20 @@ void __init ls1x_clk_init(void)
 	 *                                |_____|
 	 */
 	hw = clk_hw_register_divider(NULL, "dc_clk_div", "pll_clk",
-				   0, LS1X_CLK_PLL_DIV, DIV_DC_SHIFT,
+				   0, CLK_PLL_DIV_ADDR, DIV_DC_SHIFT,
 				   DIV_DC_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock);
-	clk_hw_register_clkdev(hw, "dc_clk_div", NULL);
-	hw = clk_hw_register_mux(NULL, "dc_clk", dc_parents,
-			       ARRAY_SIZE(dc_parents),
-			       CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV,
+	if (!hw)
+		goto err;
+	onecell->hws[LS1B_CLK_DC_DIV] = hw;
+
+	parents[0] = "dc_clk_div";
+	hw = clk_hw_register_mux(NULL, "dc_clk", parents,
+			       ARRAY_SIZE(parents),
+			       CLK_SET_RATE_NO_REPARENT, CLK_PLL_DIV_ADDR,
 			       BYPASS_DC_SHIFT, BYPASS_DC_WIDTH, 0, &_lock);
-	clk_hw_register_clkdev(hw, "dc_clk", NULL);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1B_CLK_DC] = hw;
 
 	/*                                 _____
 	 *         _______________________|     |
@@ -94,23 +141,76 @@ void __init ls1x_clk_init(void)
 	 *        \___ PLL ___ DDR DIV ___|     |
 	 *                                |_____|
 	 */
-	hw = clk_hw_register_divider(NULL, "ahb_clk_div", "pll_clk",
-				   0, LS1X_CLK_PLL_DIV, DIV_DDR_SHIFT,
+	hw = clk_hw_register_divider(NULL, "ddr_clk_div", "pll_clk",
+				   0, CLK_PLL_DIV_ADDR, DIV_DDR_SHIFT,
 				   DIV_DDR_WIDTH, CLK_DIVIDER_ONE_BASED,
 				   &_lock);
-	clk_hw_register_clkdev(hw, "ahb_clk_div", NULL);
-	hw = clk_hw_register_mux(NULL, "ahb_clk", ahb_parents,
-			       ARRAY_SIZE(ahb_parents),
-			       CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV,
+	if (!hw)
+		goto err;
+	onecell->hws[LS1B_CLK_DDR_DIV] = hw;
+
+	parents[0] = "ddr_clk_div";
+	hw = clk_hw_register_mux(NULL, "ddr_clk", parents,
+			       ARRAY_SIZE(parents),
+			       CLK_SET_RATE_NO_REPARENT, CLK_PLL_DIV_ADDR,
 			       BYPASS_DDR_SHIFT, BYPASS_DDR_WIDTH, 0, &_lock);
-	clk_hw_register_clkdev(hw, "ahb_clk", NULL);
-	clk_hw_register_clkdev(hw, "ls1x-dma", NULL);
-	clk_hw_register_clkdev(hw, "stmmaceth", NULL);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1B_CLK_DDR] = hw;
+
+	hw = clk_hw_register_fixed_factor(NULL, "ahb_clk", "ddr_clk", 0, 1,
+					1);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1B_CLK_AHB] = hw;
 
 	/* clock derived from AHB clk */
 	/* APB clk is always half of the AHB clk */
 	hw = clk_hw_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1,
 					DIV_APB);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1B_CLK_APB] = hw;
+
+	return onecell;
+
+err:
+	kfree(onecell);
+	return NULL;
+}
+
+void __init ls1b_register_clkdev(struct clk_hw_onecell_data *onecell)
+{
+	struct clk_hw *hw;
+
+	hw = onecell->hws[LS1B_CLK_PLL];
+	clk_hw_register_clkdev(hw, "pll_clk", NULL);
+
+	hw = onecell->hws[LS1B_CLK_CPU_DIV];
+	clk_hw_register_clkdev(hw, "cpu_clk_div", NULL);
+
+	hw = onecell->hws[LS1B_CLK_CPU];
+	clk_hw_register_clkdev(hw, "cpu_clk", NULL);
+
+
+	hw = onecell->hws[LS1B_CLK_DC_DIV];
+	clk_hw_register_clkdev(hw, "dc_clk_div", NULL);
+
+	hw = onecell->hws[LS1B_CLK_DC];
+	clk_hw_register_clkdev(hw, "dc_clk", NULL);
+
+	hw = onecell->hws[LS1B_CLK_DDR_DIV];
+	clk_hw_register_clkdev(hw, "ddr_clk_div", NULL);
+
+	hw = onecell->hws[LS1B_CLK_DDR];
+	clk_hw_register_clkdev(hw, "ddr_clk_div", NULL);
+
+	hw = onecell->hws[LS1B_CLK_AHB];
+	clk_hw_register_clkdev(hw, "ahb_clk", NULL);
+	clk_hw_register_clkdev(hw, "ls1x-dma", NULL);
+	clk_hw_register_clkdev(hw, "stmmaceth", NULL);
+
+	hw = onecell->hws[LS1B_CLK_APB];
 	clk_hw_register_clkdev(hw, "apb_clk", NULL);
 	clk_hw_register_clkdev(hw, "ls1x-ac97", NULL);
 	clk_hw_register_clkdev(hw, "ls1x-i2c", NULL);
diff --git a/drivers/clk/loongson1/clk-loongson1c.c b/drivers/clk/loongson1/clk-loongson1c.c
index 3466f7320b40..929e999a3cf5 100644
--- a/drivers/clk/loongson1/clk-loongson1c.c
+++ b/drivers/clk/loongson1/clk-loongson1c.c
@@ -1,21 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2016 Yang Ling <gnaygnil@gmail.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
+ * Copyright (c) 2012-2016 Zhang, Keguang <keguang.zhang@gmail.com>
+ * Copyright (c) 2019 Jiaxun Yang <jiaxun.yang@flygoat.com>
  */
 
 #include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 
-#include <loongson1.h>
 #include "clk.h"
 
-#define OSC		(24 * 1000000)
+#include <dt-bindings/clock/ls1c-clock.h>
+
+#define LS1C_CLK_COUNT	6
+
 #define DIV_APB		1
 
+/* PLL/SDRAM Frequency configuration register Bits */
+#define PLL_VALID			BIT(31)
+#define FRAC_N				GENMASK(23, 16)
+#define RST_TIME			GENMASK(3, 2)
+#define SDRAM_DIV			GENMASK(1, 0)
+
+/* CPU/CAMERA/DC Frequency configuration register Bits */
+#define DIV_DC_EN			BIT(31)
+#define DIV_DC				GENMASK(30, 24)
+#define DIV_CAM_EN			BIT(23)
+#define DIV_CAM				GENMASK(22, 16)
+#define DIV_CPU_EN			BIT(15)
+#define DIV_CPU				GENMASK(14, 8)
+#define DIV_DC_SEL_EN			BIT(5)
+#define DIV_DC_SEL			BIT(4)
+#define DIV_CAM_SEL_EN			BIT(3)
+#define DIV_CAM_SEL			BIT(2)
+#define DIV_CPU_SEL_EN			BIT(1)
+#define DIV_CPU_SEL			BIT(0)
+
+#define DIV_DC_SHIFT			24
+#define DIV_CAM_SHIFT			16
+#define DIV_CPU_SHIFT			8
+#define DIV_DDR_SHIFT			0
+
+#define DIV_DC_WIDTH			7
+#define DIV_CAM_WIDTH			7
+#define DIV_CPU_WIDTH			7
+#define DIV_DDR_WIDTH			2
+
 static DEFINE_SPINLOCK(_lock);
 
 static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw,
@@ -23,9 +52,9 @@ static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw,
 {
 	u32 pll, rate;
 
-	pll = __raw_readl(LS1X_CLK_PLL_FREQ);
+	pll = __raw_readl(CLK_PLL_FREQ_ADDR);
 	rate = ((pll >> 8) & 0xff) + ((pll >> 16) & 0xff);
-	rate *= OSC;
+	rate *= parent_rate;
 	rate >>= 2;
 
 	return rate;
@@ -42,50 +71,95 @@ static const struct clk_div_table ahb_div_table[] = {
 	[3] = { .val = 3, .div = 3 },
 };
 
-void __init ls1x_clk_init(void)
+struct clk_hw_onecell_data __init *ls1c_clk_init_hw(const char *osc_name)
 {
 	struct clk_hw *hw;
+	struct clk_hw_onecell_data *onecell;
+
+	onecell = kzalloc(sizeof(*onecell) +
+			  (LS1C_CLK_COUNT * sizeof(struct clk_hw *)),
+			  GFP_KERNEL);
+
+	if (!onecell)
+		return NULL;
 
-	hw = clk_hw_register_fixed_rate(NULL, "osc_clk", NULL, 0, OSC);
-	clk_hw_register_clkdev(hw, "osc_clk", NULL);
+	onecell->num = LS1C_CLK_COUNT;
 
-	/* clock derived from 24 MHz OSC clk */
-	hw = clk_hw_register_pll(NULL, "pll_clk", "osc_clk",
+	/* clock derived from OSC clk */
+	hw = clk_hw_register_pll(NULL, "pll_clk", osc_name,
 				&ls1x_pll_clk_ops, 0);
-	clk_hw_register_clkdev(hw, "pll_clk", NULL);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1C_CLK_PLL] = hw;
 
-	hw = clk_hw_register_divider(NULL, "cpu_clk_div", "pll_clk",
-				   CLK_GET_RATE_NOCACHE, LS1X_CLK_PLL_DIV,
+	hw = clk_hw_register_divider(NULL, "cpu_clk", "pll_clk",
+				   CLK_GET_RATE_NOCACHE, CLK_PLL_DIV_ADDR,
 				   DIV_CPU_SHIFT, DIV_CPU_WIDTH,
 				   CLK_DIVIDER_ONE_BASED |
 				   CLK_DIVIDER_ROUND_CLOSEST, &_lock);
-	clk_hw_register_clkdev(hw, "cpu_clk_div", NULL);
-	hw = clk_hw_register_fixed_factor(NULL, "cpu_clk", "cpu_clk_div",
-					0, 1, 1);
-	clk_hw_register_clkdev(hw, "cpu_clk", NULL);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1C_CLK_CPU] = hw;
+
 
-	hw = clk_hw_register_divider(NULL, "dc_clk_div", "pll_clk",
-				   0, LS1X_CLK_PLL_DIV, DIV_DC_SHIFT,
+	hw = clk_hw_register_divider(NULL, "dc_clk", "pll_clk",
+				   0, CLK_PLL_DIV_ADDR, DIV_DC_SHIFT,
 				   DIV_DC_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock);
-	clk_hw_register_clkdev(hw, "dc_clk_div", NULL);
-	hw = clk_hw_register_fixed_factor(NULL, "dc_clk", "dc_clk_div",
-					0, 1, 1);
-	clk_hw_register_clkdev(hw, "dc_clk", NULL);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1C_CLK_DC] = hw;
 
-	hw = clk_hw_register_divider_table(NULL, "ahb_clk_div", "cpu_clk_div",
-				0, LS1X_CLK_PLL_FREQ, DIV_DDR_SHIFT,
+	hw = clk_hw_register_divider_table(NULL, "ddr_clk", "cpu_clk",
+				0, CLK_PLL_FREQ_ADDR, DIV_DDR_SHIFT,
 				DIV_DDR_WIDTH, CLK_DIVIDER_ALLOW_ZERO,
 				ahb_div_table, &_lock);
-	clk_hw_register_clkdev(hw, "ahb_clk_div", NULL);
-	hw = clk_hw_register_fixed_factor(NULL, "ahb_clk", "ahb_clk_div",
+	if (!hw)
+		goto err;
+	onecell->hws[LS1C_CLK_DDR] = hw;
+
+
+	hw = clk_hw_register_fixed_factor(NULL, "ahb_clk", "ddr_clk",
 					0, 1, 1);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1C_CLK_AHB] = hw;
+
+
+	hw = clk_hw_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1,
+					DIV_APB);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1C_CLK_APB] = hw;
+
+	return onecell;
+
+err:
+	kfree(onecell);
+	return NULL;
+}
+
+void __init ls1c_register_clkdev(struct clk_hw_onecell_data *onecell)
+{
+	struct clk_hw *hw;
+
+	hw = onecell->hws[LS1C_CLK_PLL];
+	clk_hw_register_clkdev(hw, "pll_clk", NULL);
+
+	hw = onecell->hws[LS1C_CLK_CPU];
+	clk_hw_register_clkdev(hw, "cpu_clk", NULL);
+
+	hw = onecell->hws[LS1C_CLK_DC];
+	clk_hw_register_clkdev(hw, "dc_clk", NULL);
+
+	hw = onecell->hws[LS1C_CLK_DDR];
+	clk_hw_register_clkdev(hw, "ddr_clk", NULL);
+
+	hw = onecell->hws[LS1C_CLK_AHB];
 	clk_hw_register_clkdev(hw, "ahb_clk", NULL);
 	clk_hw_register_clkdev(hw, "ls1x-dma", NULL);
 	clk_hw_register_clkdev(hw, "stmmaceth", NULL);
 
-	/* clock derived from AHB clk */
-	hw = clk_hw_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1,
-					DIV_APB);
+	hw = onecell->hws[LS1C_CLK_APB];
 	clk_hw_register_clkdev(hw, "apb_clk", NULL);
 	clk_hw_register_clkdev(hw, "ls1x-ac97", NULL);
 	clk_hw_register_clkdev(hw, "ls1x-i2c", NULL);
diff --git a/drivers/clk/loongson1/clk.c b/drivers/clk/loongson1/clk.c
index 983ce9f6edbb..a1571a3a1910 100644
--- a/drivers/clk/loongson1/clk.c
+++ b/drivers/clk/loongson1/clk.c
@@ -1,14 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2012-2016 Zhang, Keguang <keguang.zhang@gmail.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
+ * Copyright (c) 2019 Jiaxun Yang <jiaxun.yang@flygoat.com>
  */
 
+#include <linux/clkdev.h>
+
 #include <linux/clk-provider.h>
 #include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+
+#include <asm/mach-loongson32/platform.h>
+
+void __iomem *clk_base;
+
+#define LS1C_OSC		(24 * 1000000)
+#define LS1B_OSC		(33 * 1000000)
+
+#define LS1X_CLK_BASE	0x1fe78030
 
 #include "clk.h"
 
@@ -43,3 +53,75 @@ struct clk_hw *__init clk_hw_register_pll(struct device *dev,
 
 	return hw;
 }
+
+
+static void __init ls1c_clk_of_setup(struct device_node *np)
+{
+	struct clk_hw_onecell_data *onecell;
+	int err;
+	const char *parent = of_clk_get_parent_name(np, 0);
+
+	clk_base = of_iomap(np, 0);
+
+	onecell = ls1c_clk_init_hw(parent);
+	if (!onecell)
+		pr_err("ls1c-clk: unable to register clk_hw");
+
+	err = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, onecell);
+	if (err)
+		pr_err("ls1c-clk: failed to add DT provider: %d\n", err);
+
+	pr_info("ls1c-clk: driver registered");
+}
+CLK_OF_DECLARE(clk_ls1c, "loongson,ls1c-clock", ls1c_clk_of_setup);
+
+static void __init ls1b_clk_of_setup(struct device_node *np)
+{
+	struct clk_hw_onecell_data *onecell;
+	int err;
+	const char *parent = of_clk_get_parent_name(np, 0);
+
+	clk_base = of_iomap(np, 0);
+
+	onecell = ls1b_clk_init_hw(parent);
+	if (!onecell)
+		pr_err("ls1b-clk: unable to register clk_hw");
+
+	err = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, onecell);
+	if (err)
+		pr_err("ls1b-clk: failed to add DT provider: %d\n", err);
+
+	pr_info("ls1b-clk: driver registered");
+}
+
+CLK_OF_DECLARE(clk_ls1b, "loongson,ls1b-clock", ls1b_clk_of_setup);
+
+
+
+void __init ls1x_clk_init(void)
+{
+	struct clk_hw *hw;
+	struct clk_hw_onecell_data *onecell;
+
+	clk_base = (void __iomem *)KSEG1ADDR(LS1X_CLK_BASE);
+#ifdef CONFIG_LOONGSON1_LS1B
+	hw = clk_hw_register_fixed_rate(NULL, "osc_clk", NULL, 0, LS1B_OSC);
+	clk_hw_register_clkdev(hw, "osc_clk", NULL);
+	onecell = ls1c_clk_init_hw("osc_clk");
+	if (!onecell)
+		panic("ls1x-clk: unable to register clk_hw");
+
+	ls1c_register_clkdev(onecell);
+#elif defined(CONFIG_LOONGSON1_LS1C)
+	hw = clk_hw_register_fixed_rate(NULL, "osc_clk", NULL, 0, LS1C_OSC);
+	clk_hw_register_clkdev(hw, "osc_clk", NULL);
+	onecell = ls1c_clk_init_hw("osc_clk");
+	if (!onecell)
+		panic("ls1x-clk: unable to register clk_hw");
+
+	ls1c_register_clkdev(onecell);
+#else
+	panic("ls1x-clk: not loongson platform");
+#endif
+}
+
diff --git a/drivers/clk/loongson1/clk.h b/drivers/clk/loongson1/clk.h
index 085d74b5d496..7895442b01f5 100644
--- a/drivers/clk/loongson1/clk.h
+++ b/drivers/clk/loongson1/clk.h
@@ -1,10 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2012-2016 Zhang, Keguang <keguang.zhang@gmail.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
+ * Copyright (c) 2019 Jiaxun Yang <jiaxun.yang@flygoat.com>
  */
 
 #ifndef __LOONGSON1_CLK_H
@@ -16,4 +13,15 @@ struct clk_hw *clk_hw_register_pll(struct device *dev,
 				   const struct clk_ops *ops,
 				   unsigned long flags);
 
+struct clk_hw_onecell_data __init *ls1c_clk_init_hw(const char *osc_name);
+struct clk_hw_onecell_data __init *ls1b_clk_init_hw(const char *osc_name);
+
+void __init ls1c_register_clkdev(struct clk_hw_onecell_data *onecell);
+void __init ls1b_register_clkdev(struct clk_hw_onecell_data *onecell);
+
+extern void __iomem *clk_base;
+
+#define CLK_PLL_FREQ_ADDR	clk_base
+#define CLK_PLL_DIV_ADDR	(clk_base + 0x4)
+
 #endif /* __LOONGSON1_CLK_H */
-- 
2.20.1


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

* [PATCH 3/3] dt-bindings: clock: Add loongson-1 clock bindings
  2019-01-25 13:34 [PATCH 0/3] Enhance loongson-1 clock driver Jiaxun Yang
  2019-01-25 13:34 ` [PATCH 1/3] clk: loongson1: add configuration option for loongson1 clks Jiaxun Yang
  2019-01-25 13:34 ` [PATCH 2/3] clk: loongson1: add of support Jiaxun Yang
@ 2019-01-25 13:34 ` Jiaxun Yang
  2019-01-28 15:20 ` [PATCH 0/3] Enhance loongson-1 clock driver Jiaxun Yang
  3 siblings, 0 replies; 16+ messages in thread
From: Jiaxun Yang @ 2019-01-25 13:34 UTC (permalink / raw)
  To: linux-mips
  Cc: mturquette, sboyd, linux-clk, linux-kernel, robh+dt,
	mark.rutland, devicetree, Jiaxun Yang

Loongson-1 is a series of MIPS MCUs.
This patch add the clock bindings for loongson-1b and
loongson-1c clock subsystem.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 .../bindings/clock/loongson1-clock.txt        | 11 ++++++++++
 include/dt-bindings/clock/ls1b-clock.h        | 20 +++++++++++++++++++
 include/dt-bindings/clock/ls1c-clock.h        | 17 ++++++++++++++++
 3 files changed, 48 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/loongson1-clock.txt
 create mode 100644 include/dt-bindings/clock/ls1b-clock.h
 create mode 100644 include/dt-bindings/clock/ls1c-clock.h

diff --git a/Documentation/devicetree/bindings/clock/loongson1-clock.txt b/Documentation/devicetree/bindings/clock/loongson1-clock.txt
new file mode 100644
index 000000000000..f0119fbd0851
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/loongson1-clock.txt
@@ -0,0 +1,11 @@
+* Clock bindings for Loongson-1 MCUs
+
+Required properties:
+- compatible: Should be "loongson,ls1c-clock" or "loongson,ls1b-clock"
+- reg: Address and length of the register set
+- #clock-cells: Should be <1>
+- clocks: list of input clocks
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell. See include/dt-bindings/clock/ls1c-clock.h
+or include/dt-bindings/clock/ls1b-clock.h for the full list of clocks.
diff --git a/include/dt-bindings/clock/ls1b-clock.h b/include/dt-bindings/clock/ls1b-clock.h
new file mode 100644
index 000000000000..814227842ae0
--- /dev/null
+++ b/include/dt-bindings/clock/ls1b-clock.h
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier:	GPL-2.0
+/*
+ * Copyright (C) 2019 Jiaxun Yang <jiaxun.yang@flygoat.com>
+ *
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_LS1B_CLOCK_H__
+#define __DT_BINDINGS_CLOCK_LS1B_CLOCK_H__
+
+#define LS1B_CLK_PLL 0
+#define LS1B_CLK_CPU_DIV 1
+#define LS1B_CLK_CPU 2
+#define LS1B_CLK_DC_DIV 3
+#define LS1B_CLK_DC 4
+#define LS1B_CLK_DDR_DIV 5
+#define LS1B_CLK_DDR 6
+#define LS1B_CLK_AHB 7
+#define LS1B_CLK_APB 8
+
+#endif /* __DT_BINDINGS_CLOCK_LS1B_CLOCK_H__ */
diff --git a/include/dt-bindings/clock/ls1c-clock.h b/include/dt-bindings/clock/ls1c-clock.h
new file mode 100644
index 000000000000..40f386cb92ce
--- /dev/null
+++ b/include/dt-bindings/clock/ls1c-clock.h
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier:	GPL-2.0
+/*
+ * Copyright (C) 2019 Jiaxun Yang <jiaxun.yang@flygoat.com>
+ *
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_LS1C_CLOCK_H__
+#define __DT_BINDINGS_CLOCK_LS1C_CLOCK_H__
+
+#define LS1C_CLK_PLL 0
+#define LS1C_CLK_CPU 1
+#define LS1C_CLK_DC 2
+#define LS1C_CLK_DDR 3
+#define LS1C_CLK_AHB 4
+#define LS1C_CLK_APB 5
+
+#endif /* __DT_BINDINGS_CLOCK_LS1C_CLOCK_H__ */
-- 
2.20.1


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

* [PATCH 0/3] Enhance loongson-1 clock driver
  2019-01-25 13:34 [PATCH 0/3] Enhance loongson-1 clock driver Jiaxun Yang
                   ` (2 preceding siblings ...)
  2019-01-25 13:34 ` [PATCH 3/3] dt-bindings: clock: Add loongson-1 clock bindings Jiaxun Yang
@ 2019-01-28 15:20 ` Jiaxun Yang
  2019-01-28 15:20   ` [PATCH v2 1/3] clk: loongson1: add configuration option for loongson1 clks Jiaxun Yang
                     ` (3 more replies)
  3 siblings, 4 replies; 16+ messages in thread
From: Jiaxun Yang @ 2019-01-28 15:20 UTC (permalink / raw)
  To: linux-mips
  Cc: mturquette, sboyd, linux-clk, linux-kernel, robh+dt,
	mark.rutland, devicetree

Add of support for ls1c-clock and ls1b-clock
v2: Move of declear into per clk file



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

* [PATCH v2 1/3] clk: loongson1: add configuration option for loongson1 clks
  2019-01-28 15:20 ` [PATCH 0/3] Enhance loongson-1 clock driver Jiaxun Yang
@ 2019-01-28 15:20   ` Jiaxun Yang
  2019-01-28 15:20   ` [PATCH v2 2/3] clk: loongson1: add of support Jiaxun Yang
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 16+ messages in thread
From: Jiaxun Yang @ 2019-01-28 15:20 UTC (permalink / raw)
  To: linux-mips
  Cc: mturquette, sboyd, linux-clk, linux-kernel, robh+dt,
	mark.rutland, devicetree, Jiaxun Yang

The patch introduces options for loongson1 clocks so we can
select the driver we need.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 drivers/clk/Kconfig            |  1 +
 drivers/clk/Makefile           |  2 +-
 drivers/clk/loongson1/Kconfig  | 27 +++++++++++++++++++++++++++
 drivers/clk/loongson1/Makefile |  7 ++++---
 4 files changed, 33 insertions(+), 4 deletions(-)
 create mode 100644 drivers/clk/loongson1/Kconfig

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index e5b2fe80eab4..136d3d73c6df 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -298,6 +298,7 @@ source "drivers/clk/imgtec/Kconfig"
 source "drivers/clk/imx/Kconfig"
 source "drivers/clk/ingenic/Kconfig"
 source "drivers/clk/keystone/Kconfig"
+source "drivers/clk/loongson1/Kconfig"
 source "drivers/clk/mediatek/Kconfig"
 source "drivers/clk/meson/Kconfig"
 source "drivers/clk/mvebu/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 8a9440a97500..7d29e545caf0 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -76,7 +76,7 @@ obj-y					+= imx/
 obj-y					+= ingenic/
 obj-$(CONFIG_ARCH_K3)			+= keystone/
 obj-$(CONFIG_ARCH_KEYSTONE)		+= keystone/
-obj-$(CONFIG_MACH_LOONGSON32)		+= loongson1/
+obj-y					+= loongson1/
 obj-y					+= mediatek/
 obj-$(CONFIG_COMMON_CLK_AMLOGIC)	+= meson/
 obj-$(CONFIG_MACH_PIC32)		+= microchip/
diff --git a/drivers/clk/loongson1/Kconfig b/drivers/clk/loongson1/Kconfig
new file mode 100644
index 000000000000..e2220332d797
--- /dev/null
+++ b/drivers/clk/loongson1/Kconfig
@@ -0,0 +1,27 @@
+menu "Loongson-1 Clock drivers"
+	depends on MACH_LOONGSON32
+
+config LOONGSON1_CLOCK_COMMON
+	bool
+
+config LOONGSON1_CLOCK_LS1B
+	bool "Loongson 1B driver"
+	default y
+	select LOONGSON1_CLOCK_COMMON
+	help
+	  Support the clocks provided by the clock hardware on Loongson-1B
+	  and compatible SoCs.
+
+	  If building for a Loongson-1B SoC, you want to say Y here.
+
+config LOONGSON1_CLOCK_LS1C
+	bool "Loongson 1C driver"
+	default y
+	select LOONGSON1_CLOCK_COMMON
+	help
+	  Support the clocks provided by the clock hardware on Loongson-1C
+	  and compatible SoCs.
+
+	  If building for a Loongson-1C SoC, you want to say Y here.
+
+endmenu
diff --git a/drivers/clk/loongson1/Makefile b/drivers/clk/loongson1/Makefile
index b7f6a16390e0..9240189183ff 100644
--- a/drivers/clk/loongson1/Makefile
+++ b/drivers/clk/loongson1/Makefile
@@ -1,3 +1,4 @@
-obj-y				+= clk.o
-obj-$(CONFIG_LOONGSON1_LS1B)	+= clk-loongson1b.o
-obj-$(CONFIG_LOONGSON1_LS1C)	+= clk-loongson1c.o
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_LOONGSON1_CLOCK_COMMON)	+= clk.o
+obj-$(CONFIG_LOONGSON1_CLOCK_LS1B)	+= clk-loongson1b.o
+obj-$(CONFIG_LOONGSON1_CLOCK_LS1C)	+= clk-loongson1c.o
-- 
2.20.1


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

* [PATCH v2 2/3] clk: loongson1: add of support
  2019-01-28 15:20 ` [PATCH 0/3] Enhance loongson-1 clock driver Jiaxun Yang
  2019-01-28 15:20   ` [PATCH v2 1/3] clk: loongson1: add configuration option for loongson1 clks Jiaxun Yang
@ 2019-01-28 15:20   ` Jiaxun Yang
  2019-01-28 15:20   ` [PATCH v2 3/3] dt-bindings: clock: Add loongson-1 clock bindings Jiaxun Yang
  2019-02-01  6:35   ` [PATCH v3 0/3] Enhance loongson-1 clock driver Jiaxun Yang
  3 siblings, 0 replies; 16+ messages in thread
From: Jiaxun Yang @ 2019-01-28 15:20 UTC (permalink / raw)
  To: linux-mips
  Cc: mturquette, sboyd, linux-clk, linux-kernel, robh+dt,
	mark.rutland, devicetree, Jiaxun Yang

This patch add of support by split the clk_hw register and
clkdev register, then handle the of clk_hw via
of_clk_hw_onecell_get.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 drivers/clk/loongson1/clk-loongson1b.c | 197 ++++++++++++++++++++-----
 drivers/clk/loongson1/clk-loongson1c.c | 164 +++++++++++++++-----
 drivers/clk/loongson1/clk.c            |  47 +++++-
 drivers/clk/loongson1/clk.h            |  18 ++-
 4 files changed, 343 insertions(+), 83 deletions(-)

diff --git a/drivers/clk/loongson1/clk-loongson1b.c b/drivers/clk/loongson1/clk-loongson1b.c
index f36a97e993c0..2148df31db15 100644
--- a/drivers/clk/loongson1/clk-loongson1b.c
+++ b/drivers/clk/loongson1/clk-loongson1b.c
@@ -1,10 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2012-2016 Zhang, Keguang <keguang.zhang@gmail.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
+ * Copyright (c) 2019 Jiaxun Yang <jiaxun.yang@flygoat.com>
  */
 
 #include <linux/clkdev.h>
@@ -12,11 +9,41 @@
 #include <linux/io.h>
 #include <linux/err.h>
 
-#include <loongson1.h>
 #include "clk.h"
+#include <dt-bindings/clock/ls1b-clock.h>
+
+#define LS1B_CLK_COUNT	9
 
-#define OSC		(33 * 1000000)
 #define DIV_APB		2
+/* Clock PLL Divisor Register Bits */
+#define DIV_DC_EN			BIT(31)
+#define DIV_DC_RST			BIT(30)
+#define DIV_CPU_EN			BIT(25)
+#define DIV_CPU_RST			BIT(24)
+#define DIV_DDR_EN			BIT(19)
+#define DIV_DDR_RST			BIT(18)
+#define RST_DC_EN			BIT(5)
+#define RST_DC				BIT(4)
+#define RST_DDR_EN			BIT(3)
+#define RST_DDR				BIT(2)
+#define RST_CPU_EN			BIT(1)
+#define RST_CPU				BIT(0)
+
+#define DIV_DC_SHIFT			26
+#define DIV_CPU_SHIFT			20
+#define DIV_DDR_SHIFT			14
+
+#define DIV_DC_WIDTH			4
+#define DIV_CPU_WIDTH			4
+#define DIV_DDR_WIDTH			4
+
+#define BYPASS_DC_SHIFT			12
+#define BYPASS_DDR_SHIFT		10
+#define BYPASS_CPU_SHIFT		8
+
+#define BYPASS_DC_WIDTH			1
+#define BYPASS_DDR_WIDTH		1
+#define BYPASS_CPU_WIDTH		1
 
 static DEFINE_SPINLOCK(_lock);
 
@@ -25,9 +52,9 @@ static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw,
 {
 	u32 pll, rate;
 
-	pll = __raw_readl(LS1X_CLK_PLL_FREQ);
+	pll = __raw_readl(CLK_PLL_FREQ_ADDR);
 	rate = 12 + (pll & GENMASK(5, 0));
-	rate *= OSC;
+	rate *= parent_rate;
 	rate >>= 1;
 
 	return rate;
@@ -37,21 +64,29 @@ static const struct clk_ops ls1x_pll_clk_ops = {
 	.recalc_rate = ls1x_pll_recalc_rate,
 };
 
-static const char *const cpu_parents[] = { "cpu_clk_div", "osc_clk", };
-static const char *const ahb_parents[] = { "ahb_clk_div", "osc_clk", };
-static const char *const dc_parents[] = { "dc_clk_div", "osc_clk", };
 
-void __init ls1x_clk_init(void)
+struct clk_hw_onecell_data __init *ls1b_clk_init_hw(const char *osc_name)
 {
 	struct clk_hw *hw;
+	struct clk_hw_onecell_data *onecell;
+	const char *parents[2];
+
+	onecell = kzalloc(sizeof(*onecell) +
+			  (LS1B_CLK_COUNT * sizeof(struct clk_hw *)),
+			  GFP_KERNEL);
+
+	if (!onecell)
+		return NULL;
 
-	hw = clk_hw_register_fixed_rate(NULL, "osc_clk", NULL, 0, OSC);
-	clk_hw_register_clkdev(hw, "osc_clk", NULL);
+	onecell->num = LS1B_CLK_COUNT;
 
+	parents[1] = osc_name;
 	/* clock derived from 33 MHz OSC clk */
-	hw = clk_hw_register_pll(NULL, "pll_clk", "osc_clk",
+	hw = clk_hw_register_pll(NULL, "pll_clk", osc_name,
 				 &ls1x_pll_clk_ops, 0);
-	clk_hw_register_clkdev(hw, "pll_clk", NULL);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1B_CLK_PLL] = hw;
 
 	/* clock derived from PLL clk */
 	/*                                 _____
@@ -61,16 +96,22 @@ void __init ls1x_clk_init(void)
 	 *                                |_____|
 	 */
 	hw = clk_hw_register_divider(NULL, "cpu_clk_div", "pll_clk",
-				   CLK_GET_RATE_NOCACHE, LS1X_CLK_PLL_DIV,
+				   CLK_GET_RATE_NOCACHE, CLK_PLL_DIV_ADDR,
 				   DIV_CPU_SHIFT, DIV_CPU_WIDTH,
 				   CLK_DIVIDER_ONE_BASED |
 				   CLK_DIVIDER_ROUND_CLOSEST, &_lock);
-	clk_hw_register_clkdev(hw, "cpu_clk_div", NULL);
-	hw = clk_hw_register_mux(NULL, "cpu_clk", cpu_parents,
-			       ARRAY_SIZE(cpu_parents),
-			       CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV,
+	if (!hw)
+		goto err;
+	onecell->hws[LS1B_CLK_CPU_DIV] = hw;
+
+	parents[0] = "cpu_clk_div";
+	hw = clk_hw_register_mux(NULL, "cpu_clk", parents,
+			       ARRAY_SIZE(parents),
+			       CLK_SET_RATE_NO_REPARENT, CLK_PLL_DIV_ADDR,
 			       BYPASS_CPU_SHIFT, BYPASS_CPU_WIDTH, 0, &_lock);
-	clk_hw_register_clkdev(hw, "cpu_clk", NULL);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1B_CLK_CPU] = hw;
 
 	/*                                 _____
 	 *         _______________________|     |
@@ -79,14 +120,20 @@ void __init ls1x_clk_init(void)
 	 *                                |_____|
 	 */
 	hw = clk_hw_register_divider(NULL, "dc_clk_div", "pll_clk",
-				   0, LS1X_CLK_PLL_DIV, DIV_DC_SHIFT,
+				   0, CLK_PLL_DIV_ADDR, DIV_DC_SHIFT,
 				   DIV_DC_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock);
-	clk_hw_register_clkdev(hw, "dc_clk_div", NULL);
-	hw = clk_hw_register_mux(NULL, "dc_clk", dc_parents,
-			       ARRAY_SIZE(dc_parents),
-			       CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV,
+	if (!hw)
+		goto err;
+	onecell->hws[LS1B_CLK_DC_DIV] = hw;
+
+	parents[0] = "dc_clk_div";
+	hw = clk_hw_register_mux(NULL, "dc_clk", parents,
+			       ARRAY_SIZE(parents),
+			       CLK_SET_RATE_NO_REPARENT, CLK_PLL_DIV_ADDR,
 			       BYPASS_DC_SHIFT, BYPASS_DC_WIDTH, 0, &_lock);
-	clk_hw_register_clkdev(hw, "dc_clk", NULL);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1B_CLK_DC] = hw;
 
 	/*                                 _____
 	 *         _______________________|     |
@@ -94,23 +141,76 @@ void __init ls1x_clk_init(void)
 	 *        \___ PLL ___ DDR DIV ___|     |
 	 *                                |_____|
 	 */
-	hw = clk_hw_register_divider(NULL, "ahb_clk_div", "pll_clk",
-				   0, LS1X_CLK_PLL_DIV, DIV_DDR_SHIFT,
+	hw = clk_hw_register_divider(NULL, "ddr_clk_div", "pll_clk",
+				   0, CLK_PLL_DIV_ADDR, DIV_DDR_SHIFT,
 				   DIV_DDR_WIDTH, CLK_DIVIDER_ONE_BASED,
 				   &_lock);
-	clk_hw_register_clkdev(hw, "ahb_clk_div", NULL);
-	hw = clk_hw_register_mux(NULL, "ahb_clk", ahb_parents,
-			       ARRAY_SIZE(ahb_parents),
-			       CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV,
+	if (!hw)
+		goto err;
+	onecell->hws[LS1B_CLK_DDR_DIV] = hw;
+
+	parents[0] = "ddr_clk_div";
+	hw = clk_hw_register_mux(NULL, "ddr_clk", parents,
+			       ARRAY_SIZE(parents),
+			       CLK_SET_RATE_NO_REPARENT, CLK_PLL_DIV_ADDR,
 			       BYPASS_DDR_SHIFT, BYPASS_DDR_WIDTH, 0, &_lock);
-	clk_hw_register_clkdev(hw, "ahb_clk", NULL);
-	clk_hw_register_clkdev(hw, "ls1x-dma", NULL);
-	clk_hw_register_clkdev(hw, "stmmaceth", NULL);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1B_CLK_DDR] = hw;
+
+	hw = clk_hw_register_fixed_factor(NULL, "ahb_clk", "ddr_clk", 0, 1,
+					1);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1B_CLK_AHB] = hw;
 
 	/* clock derived from AHB clk */
 	/* APB clk is always half of the AHB clk */
 	hw = clk_hw_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1,
 					DIV_APB);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1B_CLK_APB] = hw;
+
+	return onecell;
+
+err:
+	kfree(onecell);
+	return NULL;
+}
+
+void __maybe_unused __init ls1b_register_clkdev(struct clk_hw_onecell_data *onecell)
+{
+	struct clk_hw *hw;
+
+	hw = onecell->hws[LS1B_CLK_PLL];
+	clk_hw_register_clkdev(hw, "pll_clk", NULL);
+
+	hw = onecell->hws[LS1B_CLK_CPU_DIV];
+	clk_hw_register_clkdev(hw, "cpu_clk_div", NULL);
+
+	hw = onecell->hws[LS1B_CLK_CPU];
+	clk_hw_register_clkdev(hw, "cpu_clk", NULL);
+
+
+	hw = onecell->hws[LS1B_CLK_DC_DIV];
+	clk_hw_register_clkdev(hw, "dc_clk_div", NULL);
+
+	hw = onecell->hws[LS1B_CLK_DC];
+	clk_hw_register_clkdev(hw, "dc_clk", NULL);
+
+	hw = onecell->hws[LS1B_CLK_DDR_DIV];
+	clk_hw_register_clkdev(hw, "ddr_clk_div", NULL);
+
+	hw = onecell->hws[LS1B_CLK_DDR];
+	clk_hw_register_clkdev(hw, "ddr_clk_div", NULL);
+
+	hw = onecell->hws[LS1B_CLK_AHB];
+	clk_hw_register_clkdev(hw, "ahb_clk", NULL);
+	clk_hw_register_clkdev(hw, "ls1x-dma", NULL);
+	clk_hw_register_clkdev(hw, "stmmaceth", NULL);
+
+	hw = onecell->hws[LS1B_CLK_APB];
 	clk_hw_register_clkdev(hw, "apb_clk", NULL);
 	clk_hw_register_clkdev(hw, "ls1x-ac97", NULL);
 	clk_hw_register_clkdev(hw, "ls1x-i2c", NULL);
@@ -120,3 +220,24 @@ void __init ls1x_clk_init(void)
 	clk_hw_register_clkdev(hw, "ls1x-wdt", NULL);
 	clk_hw_register_clkdev(hw, "serial8250", NULL);
 }
+
+static void __init ls1b_clk_of_setup(struct device_node *np)
+{
+	struct clk_hw_onecell_data *onecell;
+	int err;
+	const char *parent = of_clk_get_parent_name(np, 0);
+
+	clk_base = of_iomap(np, 0);
+
+	onecell = ls1b_clk_init_hw(parent);
+	if (!onecell)
+		pr_err("ls1b-clk: unable to register clk_hw");
+
+	err = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, onecell);
+	if (err)
+		pr_err("ls1b-clk: failed to add DT provider: %d\n", err);
+
+	pr_info("ls1b-clk: driver registered");
+}
+
+CLK_OF_DECLARE(clk_ls1b, "loongson,ls1b-clock", ls1b_clk_of_setup);
diff --git a/drivers/clk/loongson1/clk-loongson1c.c b/drivers/clk/loongson1/clk-loongson1c.c
index 3466f7320b40..076a2e1d5df9 100644
--- a/drivers/clk/loongson1/clk-loongson1c.c
+++ b/drivers/clk/loongson1/clk-loongson1c.c
@@ -1,21 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2016 Yang Ling <gnaygnil@gmail.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
+ * Copyright (c) 2012-2016 Zhang, Keguang <keguang.zhang@gmail.com>
+ * Copyright (c) 2019 Jiaxun Yang <jiaxun.yang@flygoat.com>
  */
 
 #include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 
-#include <loongson1.h>
 #include "clk.h"
 
-#define OSC		(24 * 1000000)
+#include <dt-bindings/clock/ls1c-clock.h>
+
+#define LS1C_CLK_COUNT	6
+
 #define DIV_APB		1
 
+/* PLL/SDRAM Frequency configuration register Bits */
+#define PLL_VALID			BIT(31)
+#define FRAC_N				GENMASK(23, 16)
+#define RST_TIME			GENMASK(3, 2)
+#define SDRAM_DIV			GENMASK(1, 0)
+
+/* CPU/CAMERA/DC Frequency configuration register Bits */
+#define DIV_DC_EN			BIT(31)
+#define DIV_DC				GENMASK(30, 24)
+#define DIV_CAM_EN			BIT(23)
+#define DIV_CAM				GENMASK(22, 16)
+#define DIV_CPU_EN			BIT(15)
+#define DIV_CPU				GENMASK(14, 8)
+#define DIV_DC_SEL_EN			BIT(5)
+#define DIV_DC_SEL			BIT(4)
+#define DIV_CAM_SEL_EN			BIT(3)
+#define DIV_CAM_SEL			BIT(2)
+#define DIV_CPU_SEL_EN			BIT(1)
+#define DIV_CPU_SEL			BIT(0)
+
+#define DIV_DC_SHIFT			24
+#define DIV_CAM_SHIFT			16
+#define DIV_CPU_SHIFT			8
+#define DIV_DDR_SHIFT			0
+
+#define DIV_DC_WIDTH			7
+#define DIV_CAM_WIDTH			7
+#define DIV_CPU_WIDTH			7
+#define DIV_DDR_WIDTH			2
+
 static DEFINE_SPINLOCK(_lock);
 
 static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw,
@@ -23,9 +52,9 @@ static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw,
 {
 	u32 pll, rate;
 
-	pll = __raw_readl(LS1X_CLK_PLL_FREQ);
+	pll = __raw_readl(CLK_PLL_FREQ_ADDR);
 	rate = ((pll >> 8) & 0xff) + ((pll >> 16) & 0xff);
-	rate *= OSC;
+	rate *= parent_rate;
 	rate >>= 2;
 
 	return rate;
@@ -42,50 +71,95 @@ static const struct clk_div_table ahb_div_table[] = {
 	[3] = { .val = 3, .div = 3 },
 };
 
-void __init ls1x_clk_init(void)
+struct clk_hw_onecell_data __init *ls1c_clk_init_hw(const char *osc_name)
 {
 	struct clk_hw *hw;
+	struct clk_hw_onecell_data *onecell;
+
+	onecell = kzalloc(sizeof(*onecell) +
+			  (LS1C_CLK_COUNT * sizeof(struct clk_hw *)),
+			  GFP_KERNEL);
+
+	if (!onecell)
+		return NULL;
 
-	hw = clk_hw_register_fixed_rate(NULL, "osc_clk", NULL, 0, OSC);
-	clk_hw_register_clkdev(hw, "osc_clk", NULL);
+	onecell->num = LS1C_CLK_COUNT;
 
-	/* clock derived from 24 MHz OSC clk */
-	hw = clk_hw_register_pll(NULL, "pll_clk", "osc_clk",
+	/* clock derived from OSC clk */
+	hw = clk_hw_register_pll(NULL, "pll_clk", osc_name,
 				&ls1x_pll_clk_ops, 0);
-	clk_hw_register_clkdev(hw, "pll_clk", NULL);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1C_CLK_PLL] = hw;
 
-	hw = clk_hw_register_divider(NULL, "cpu_clk_div", "pll_clk",
-				   CLK_GET_RATE_NOCACHE, LS1X_CLK_PLL_DIV,
+	hw = clk_hw_register_divider(NULL, "cpu_clk", "pll_clk",
+				   CLK_GET_RATE_NOCACHE, CLK_PLL_DIV_ADDR,
 				   DIV_CPU_SHIFT, DIV_CPU_WIDTH,
 				   CLK_DIVIDER_ONE_BASED |
 				   CLK_DIVIDER_ROUND_CLOSEST, &_lock);
-	clk_hw_register_clkdev(hw, "cpu_clk_div", NULL);
-	hw = clk_hw_register_fixed_factor(NULL, "cpu_clk", "cpu_clk_div",
-					0, 1, 1);
-	clk_hw_register_clkdev(hw, "cpu_clk", NULL);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1C_CLK_CPU] = hw;
 
-	hw = clk_hw_register_divider(NULL, "dc_clk_div", "pll_clk",
-				   0, LS1X_CLK_PLL_DIV, DIV_DC_SHIFT,
+
+	hw = clk_hw_register_divider(NULL, "dc_clk", "pll_clk",
+				   0, CLK_PLL_DIV_ADDR, DIV_DC_SHIFT,
 				   DIV_DC_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock);
-	clk_hw_register_clkdev(hw, "dc_clk_div", NULL);
-	hw = clk_hw_register_fixed_factor(NULL, "dc_clk", "dc_clk_div",
-					0, 1, 1);
-	clk_hw_register_clkdev(hw, "dc_clk", NULL);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1C_CLK_DC] = hw;
 
-	hw = clk_hw_register_divider_table(NULL, "ahb_clk_div", "cpu_clk_div",
-				0, LS1X_CLK_PLL_FREQ, DIV_DDR_SHIFT,
+	hw = clk_hw_register_divider_table(NULL, "ddr_clk", "cpu_clk",
+				0, CLK_PLL_FREQ_ADDR, DIV_DDR_SHIFT,
 				DIV_DDR_WIDTH, CLK_DIVIDER_ALLOW_ZERO,
 				ahb_div_table, &_lock);
-	clk_hw_register_clkdev(hw, "ahb_clk_div", NULL);
-	hw = clk_hw_register_fixed_factor(NULL, "ahb_clk", "ahb_clk_div",
+	if (!hw)
+		goto err;
+	onecell->hws[LS1C_CLK_DDR] = hw;
+
+
+	hw = clk_hw_register_fixed_factor(NULL, "ahb_clk", "ddr_clk",
 					0, 1, 1);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1C_CLK_AHB] = hw;
+
+
+	hw = clk_hw_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1,
+					DIV_APB);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1C_CLK_APB] = hw;
+
+	return onecell;
+
+err:
+	kfree(onecell);
+	return NULL;
+}
+
+void __maybe_unused __init ls1c_register_clkdev(struct clk_hw_onecell_data *onecell)
+{
+	struct clk_hw *hw;
+
+	hw = onecell->hws[LS1C_CLK_PLL];
+	clk_hw_register_clkdev(hw, "pll_clk", NULL);
+
+	hw = onecell->hws[LS1C_CLK_CPU];
+	clk_hw_register_clkdev(hw, "cpu_clk", NULL);
+
+	hw = onecell->hws[LS1C_CLK_DC];
+	clk_hw_register_clkdev(hw, "dc_clk", NULL);
+
+	hw = onecell->hws[LS1C_CLK_DDR];
+	clk_hw_register_clkdev(hw, "ddr_clk", NULL);
+
+	hw = onecell->hws[LS1C_CLK_AHB];
 	clk_hw_register_clkdev(hw, "ahb_clk", NULL);
 	clk_hw_register_clkdev(hw, "ls1x-dma", NULL);
 	clk_hw_register_clkdev(hw, "stmmaceth", NULL);
 
-	/* clock derived from AHB clk */
-	hw = clk_hw_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1,
-					DIV_APB);
+	hw = onecell->hws[LS1C_CLK_APB];
 	clk_hw_register_clkdev(hw, "apb_clk", NULL);
 	clk_hw_register_clkdev(hw, "ls1x-ac97", NULL);
 	clk_hw_register_clkdev(hw, "ls1x-i2c", NULL);
@@ -95,3 +169,23 @@ void __init ls1x_clk_init(void)
 	clk_hw_register_clkdev(hw, "ls1x-wdt", NULL);
 	clk_hw_register_clkdev(hw, "serial8250", NULL);
 }
+
+static void __init ls1c_clk_of_setup(struct device_node *np)
+{
+	struct clk_hw_onecell_data *onecell;
+	int err;
+	const char *parent = of_clk_get_parent_name(np, 0);
+
+	clk_base = of_iomap(np, 0);
+
+	onecell = ls1c_clk_init_hw(parent);
+	if (!onecell)
+		pr_err("ls1c-clk: unable to register clk_hw");
+
+	err = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, onecell);
+	if (err)
+		pr_err("ls1c-clk: failed to add DT provider: %d\n", err);
+
+	pr_info("ls1c-clk: driver registered");
+}
+CLK_OF_DECLARE(clk_ls1c, "loongson,ls1c-clock", ls1c_clk_of_setup);
diff --git a/drivers/clk/loongson1/clk.c b/drivers/clk/loongson1/clk.c
index 983ce9f6edbb..b4dc7dd8e0cd 100644
--- a/drivers/clk/loongson1/clk.c
+++ b/drivers/clk/loongson1/clk.c
@@ -1,14 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2012-2016 Zhang, Keguang <keguang.zhang@gmail.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
+ * Copyright (c) 2019 Jiaxun Yang <jiaxun.yang@flygoat.com>
  */
 
+#include <linux/clkdev.h>
+
 #include <linux/clk-provider.h>
 #include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+
+#include <asm/mach-loongson32/platform.h>
+
+void __iomem *clk_base;
+
+#define LS1C_OSC		(24 * 1000000)
+#define LS1B_OSC		(33 * 1000000)
+
+#define LS1X_CLK_BASE	0x1fe78030
 
 #include "clk.h"
 
@@ -43,3 +53,30 @@ struct clk_hw *__init clk_hw_register_pll(struct device *dev,
 
 	return hw;
 }
+
+void __init ls1x_clk_init(void)
+{
+	struct clk_hw *hw;
+	struct clk_hw_onecell_data *onecell;
+
+	clk_base = (void __iomem *)KSEG1ADDR(LS1X_CLK_BASE);
+#ifdef CONFIG_LOONGSON1_LS1B
+	hw = clk_hw_register_fixed_rate(NULL, "osc_clk", NULL, 0, LS1B_OSC);
+	clk_hw_register_clkdev(hw, "osc_clk", NULL);
+	onecell = ls1c_clk_init_hw("osc_clk");
+	if (!onecell)
+		panic("ls1x-clk: unable to register clk_hw");
+
+	ls1c_register_clkdev(onecell);
+#elif defined(CONFIG_LOONGSON1_LS1C)
+	hw = clk_hw_register_fixed_rate(NULL, "osc_clk", NULL, 0, LS1C_OSC);
+	clk_hw_register_clkdev(hw, "osc_clk", NULL);
+	onecell = ls1c_clk_init_hw("osc_clk");
+	if (!onecell)
+		panic("ls1x-clk: unable to register clk_hw");
+
+	ls1c_register_clkdev(onecell);
+#else
+	panic("ls1x-clk: not loongson platform");
+#endif
+}
diff --git a/drivers/clk/loongson1/clk.h b/drivers/clk/loongson1/clk.h
index 085d74b5d496..be7cc72c0ea3 100644
--- a/drivers/clk/loongson1/clk.h
+++ b/drivers/clk/loongson1/clk.h
@@ -1,10 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2012-2016 Zhang, Keguang <keguang.zhang@gmail.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
+ * Copyright (c) 2019 Jiaxun Yang <jiaxun.yang@flygoat.com>
  */
 
 #ifndef __LOONGSON1_CLK_H
@@ -16,4 +13,15 @@ struct clk_hw *clk_hw_register_pll(struct device *dev,
 				   const struct clk_ops *ops,
 				   unsigned long flags);
 
+struct clk_hw_onecell_data __init *ls1c_clk_init_hw(const char *osc_name);
+struct clk_hw_onecell_data __init *ls1b_clk_init_hw(const char *osc_name);
+
+void __maybe_unused __init ls1c_register_clkdev(struct clk_hw_onecell_data *onecell);
+void __maybe_unused __init ls1b_register_clkdev(struct clk_hw_onecell_data *onecell);
+
+extern void __iomem *clk_base;
+
+#define CLK_PLL_FREQ_ADDR	clk_base
+#define CLK_PLL_DIV_ADDR	(clk_base + 0x4)
+
 #endif /* __LOONGSON1_CLK_H */
-- 
2.20.1


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

* [PATCH v2 3/3] dt-bindings: clock: Add loongson-1 clock bindings
  2019-01-28 15:20 ` [PATCH 0/3] Enhance loongson-1 clock driver Jiaxun Yang
  2019-01-28 15:20   ` [PATCH v2 1/3] clk: loongson1: add configuration option for loongson1 clks Jiaxun Yang
  2019-01-28 15:20   ` [PATCH v2 2/3] clk: loongson1: add of support Jiaxun Yang
@ 2019-01-28 15:20   ` Jiaxun Yang
  2019-01-30 19:47     ` Rob Herring
  2019-02-01  6:35   ` [PATCH v3 0/3] Enhance loongson-1 clock driver Jiaxun Yang
  3 siblings, 1 reply; 16+ messages in thread
From: Jiaxun Yang @ 2019-01-28 15:20 UTC (permalink / raw)
  To: linux-mips
  Cc: mturquette, sboyd, linux-clk, linux-kernel, robh+dt,
	mark.rutland, devicetree, Jiaxun Yang

Loongson-1 is a series of MIPS MCUs.
This patch add the clock bindings for loongson-1b and
loongson-1c clock subsystem.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 .../bindings/clock/loongson1-clock.txt        | 11 ++++++++++
 include/dt-bindings/clock/ls1b-clock.h        | 20 +++++++++++++++++++
 include/dt-bindings/clock/ls1c-clock.h        | 17 ++++++++++++++++
 3 files changed, 48 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/loongson1-clock.txt
 create mode 100644 include/dt-bindings/clock/ls1b-clock.h
 create mode 100644 include/dt-bindings/clock/ls1c-clock.h

diff --git a/Documentation/devicetree/bindings/clock/loongson1-clock.txt b/Documentation/devicetree/bindings/clock/loongson1-clock.txt
new file mode 100644
index 000000000000..f0119fbd0851
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/loongson1-clock.txt
@@ -0,0 +1,11 @@
+* Clock bindings for Loongson-1 MCUs
+
+Required properties:
+- compatible: Should be "loongson,ls1c-clock" or "loongson,ls1b-clock"
+- reg: Address and length of the register set
+- #clock-cells: Should be <1>
+- clocks: list of input clocks
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell. See include/dt-bindings/clock/ls1c-clock.h
+or include/dt-bindings/clock/ls1b-clock.h for the full list of clocks.
diff --git a/include/dt-bindings/clock/ls1b-clock.h b/include/dt-bindings/clock/ls1b-clock.h
new file mode 100644
index 000000000000..814227842ae0
--- /dev/null
+++ b/include/dt-bindings/clock/ls1b-clock.h
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier:	GPL-2.0
+/*
+ * Copyright (C) 2019 Jiaxun Yang <jiaxun.yang@flygoat.com>
+ *
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_LS1B_CLOCK_H__
+#define __DT_BINDINGS_CLOCK_LS1B_CLOCK_H__
+
+#define LS1B_CLK_PLL 0
+#define LS1B_CLK_CPU_DIV 1
+#define LS1B_CLK_CPU 2
+#define LS1B_CLK_DC_DIV 3
+#define LS1B_CLK_DC 4
+#define LS1B_CLK_DDR_DIV 5
+#define LS1B_CLK_DDR 6
+#define LS1B_CLK_AHB 7
+#define LS1B_CLK_APB 8
+
+#endif /* __DT_BINDINGS_CLOCK_LS1B_CLOCK_H__ */
diff --git a/include/dt-bindings/clock/ls1c-clock.h b/include/dt-bindings/clock/ls1c-clock.h
new file mode 100644
index 000000000000..40f386cb92ce
--- /dev/null
+++ b/include/dt-bindings/clock/ls1c-clock.h
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier:	GPL-2.0
+/*
+ * Copyright (C) 2019 Jiaxun Yang <jiaxun.yang@flygoat.com>
+ *
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_LS1C_CLOCK_H__
+#define __DT_BINDINGS_CLOCK_LS1C_CLOCK_H__
+
+#define LS1C_CLK_PLL 0
+#define LS1C_CLK_CPU 1
+#define LS1C_CLK_DC 2
+#define LS1C_CLK_DDR 3
+#define LS1C_CLK_AHB 4
+#define LS1C_CLK_APB 5
+
+#endif /* __DT_BINDINGS_CLOCK_LS1C_CLOCK_H__ */
-- 
2.20.1


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

* Re: [PATCH v2 3/3] dt-bindings: clock: Add loongson-1 clock bindings
  2019-01-28 15:20   ` [PATCH v2 3/3] dt-bindings: clock: Add loongson-1 clock bindings Jiaxun Yang
@ 2019-01-30 19:47     ` Rob Herring
  0 siblings, 0 replies; 16+ messages in thread
From: Rob Herring @ 2019-01-30 19:47 UTC (permalink / raw)
  To: Jiaxun Yang
  Cc: linux-mips, mturquette, sboyd, linux-clk, linux-kernel,
	mark.rutland, devicetree

On Mon, Jan 28, 2019 at 11:20:52PM +0800, Jiaxun Yang wrote:
> Loongson-1 is a series of MIPS MCUs.
> This patch add the clock bindings for loongson-1b and
> loongson-1c clock subsystem.
> 
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
>  .../bindings/clock/loongson1-clock.txt        | 11 ++++++++++
>  include/dt-bindings/clock/ls1b-clock.h        | 20 +++++++++++++++++++
>  include/dt-bindings/clock/ls1c-clock.h        | 17 ++++++++++++++++
>  3 files changed, 48 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/loongson1-clock.txt
>  create mode 100644 include/dt-bindings/clock/ls1b-clock.h
>  create mode 100644 include/dt-bindings/clock/ls1c-clock.h
> 
> diff --git a/Documentation/devicetree/bindings/clock/loongson1-clock.txt b/Documentation/devicetree/bindings/clock/loongson1-clock.txt
> new file mode 100644
> index 000000000000..f0119fbd0851
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/loongson1-clock.txt
> @@ -0,0 +1,11 @@
> +* Clock bindings for Loongson-1 MCUs
> +
> +Required properties:
> +- compatible: Should be "loongson,ls1c-clock" or "loongson,ls1b-clock"

List one per line please.

> +- reg: Address and length of the register set
> +- #clock-cells: Should be <1>
> +- clocks: list of input clocks
> +
> +The clock consumer should specify the desired clock by having the clock
> +ID in its "clocks" phandle cell. See include/dt-bindings/clock/ls1c-clock.h
> +or include/dt-bindings/clock/ls1b-clock.h for the full list of clocks.
> diff --git a/include/dt-bindings/clock/ls1b-clock.h b/include/dt-bindings/clock/ls1b-clock.h
> new file mode 100644
> index 000000000000..814227842ae0
> --- /dev/null
> +++ b/include/dt-bindings/clock/ls1b-clock.h
> @@ -0,0 +1,20 @@
> +// SPDX-License-Identifier:	GPL-2.0

Headers should be /* */ style comments.

> +/*
> + * Copyright (C) 2019 Jiaxun Yang <jiaxun.yang@flygoat.com>
> + *
> + */
> +
> +#ifndef __DT_BINDINGS_CLOCK_LS1B_CLOCK_H__
> +#define __DT_BINDINGS_CLOCK_LS1B_CLOCK_H__
> +
> +#define LS1B_CLK_PLL 0
> +#define LS1B_CLK_CPU_DIV 1
> +#define LS1B_CLK_CPU 2
> +#define LS1B_CLK_DC_DIV 3
> +#define LS1B_CLK_DC 4
> +#define LS1B_CLK_DDR_DIV 5
> +#define LS1B_CLK_DDR 6
> +#define LS1B_CLK_AHB 7
> +#define LS1B_CLK_APB 8
> +
> +#endif /* __DT_BINDINGS_CLOCK_LS1B_CLOCK_H__ */
> diff --git a/include/dt-bindings/clock/ls1c-clock.h b/include/dt-bindings/clock/ls1c-clock.h
> new file mode 100644
> index 000000000000..40f386cb92ce
> --- /dev/null
> +++ b/include/dt-bindings/clock/ls1c-clock.h
> @@ -0,0 +1,17 @@
> +// SPDX-License-Identifier:	GPL-2.0
> +/*
> + * Copyright (C) 2019 Jiaxun Yang <jiaxun.yang@flygoat.com>
> + *
> + */
> +
> +#ifndef __DT_BINDINGS_CLOCK_LS1C_CLOCK_H__
> +#define __DT_BINDINGS_CLOCK_LS1C_CLOCK_H__
> +
> +#define LS1C_CLK_PLL 0
> +#define LS1C_CLK_CPU 1
> +#define LS1C_CLK_DC 2
> +#define LS1C_CLK_DDR 3
> +#define LS1C_CLK_AHB 4
> +#define LS1C_CLK_APB 5
> +
> +#endif /* __DT_BINDINGS_CLOCK_LS1C_CLOCK_H__ */
> -- 
> 2.20.1
> 

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

* [PATCH v3 0/3] Enhance loongson-1 clock driver
  2019-01-28 15:20 ` [PATCH 0/3] Enhance loongson-1 clock driver Jiaxun Yang
                     ` (2 preceding siblings ...)
  2019-01-28 15:20   ` [PATCH v2 3/3] dt-bindings: clock: Add loongson-1 clock bindings Jiaxun Yang
@ 2019-02-01  6:35   ` Jiaxun Yang
  2019-02-01  6:35     ` [PATCH v3 1/3] clk: loongson1: add configuration option for loongson1 clks Jiaxun Yang
                       ` (2 more replies)
  3 siblings, 3 replies; 16+ messages in thread
From: Jiaxun Yang @ 2019-02-01  6:35 UTC (permalink / raw)
  To: linux-mips
  Cc: mturquette, sboyd, linux-clk, linux-kernel, robh+dt,
	mark.rutland, devicetree

v2->v3: Fix dt-bindings issues



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

* [PATCH v3 1/3] clk: loongson1: add configuration option for loongson1 clks
  2019-02-01  6:35   ` [PATCH v3 0/3] Enhance loongson-1 clock driver Jiaxun Yang
@ 2019-02-01  6:35     ` Jiaxun Yang
  2019-02-06 19:18       ` Stephen Boyd
  2019-02-01  6:35     ` [PATCH v3 2/3] clk: loongson1: add of support Jiaxun Yang
  2019-02-01  6:35     ` [PATCH v3 3/3] dt-bindings: clock: Add loongson-1 clock bindings Jiaxun Yang
  2 siblings, 1 reply; 16+ messages in thread
From: Jiaxun Yang @ 2019-02-01  6:35 UTC (permalink / raw)
  To: linux-mips
  Cc: mturquette, sboyd, linux-clk, linux-kernel, robh+dt,
	mark.rutland, devicetree, Jiaxun Yang

The patch introduces options for loongson1 clocks so we can
select the driver we need.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 drivers/clk/Kconfig            |  1 +
 drivers/clk/Makefile           |  2 +-
 drivers/clk/loongson1/Kconfig  | 27 +++++++++++++++++++++++++++
 drivers/clk/loongson1/Makefile |  7 ++++---
 4 files changed, 33 insertions(+), 4 deletions(-)
 create mode 100644 drivers/clk/loongson1/Kconfig

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index e5b2fe80eab4..136d3d73c6df 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -298,6 +298,7 @@ source "drivers/clk/imgtec/Kconfig"
 source "drivers/clk/imx/Kconfig"
 source "drivers/clk/ingenic/Kconfig"
 source "drivers/clk/keystone/Kconfig"
+source "drivers/clk/loongson1/Kconfig"
 source "drivers/clk/mediatek/Kconfig"
 source "drivers/clk/meson/Kconfig"
 source "drivers/clk/mvebu/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 8a9440a97500..7d29e545caf0 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -76,7 +76,7 @@ obj-y					+= imx/
 obj-y					+= ingenic/
 obj-$(CONFIG_ARCH_K3)			+= keystone/
 obj-$(CONFIG_ARCH_KEYSTONE)		+= keystone/
-obj-$(CONFIG_MACH_LOONGSON32)		+= loongson1/
+obj-y					+= loongson1/
 obj-y					+= mediatek/
 obj-$(CONFIG_COMMON_CLK_AMLOGIC)	+= meson/
 obj-$(CONFIG_MACH_PIC32)		+= microchip/
diff --git a/drivers/clk/loongson1/Kconfig b/drivers/clk/loongson1/Kconfig
new file mode 100644
index 000000000000..e2220332d797
--- /dev/null
+++ b/drivers/clk/loongson1/Kconfig
@@ -0,0 +1,27 @@
+menu "Loongson-1 Clock drivers"
+	depends on MACH_LOONGSON32
+
+config LOONGSON1_CLOCK_COMMON
+	bool
+
+config LOONGSON1_CLOCK_LS1B
+	bool "Loongson 1B driver"
+	default y
+	select LOONGSON1_CLOCK_COMMON
+	help
+	  Support the clocks provided by the clock hardware on Loongson-1B
+	  and compatible SoCs.
+
+	  If building for a Loongson-1B SoC, you want to say Y here.
+
+config LOONGSON1_CLOCK_LS1C
+	bool "Loongson 1C driver"
+	default y
+	select LOONGSON1_CLOCK_COMMON
+	help
+	  Support the clocks provided by the clock hardware on Loongson-1C
+	  and compatible SoCs.
+
+	  If building for a Loongson-1C SoC, you want to say Y here.
+
+endmenu
diff --git a/drivers/clk/loongson1/Makefile b/drivers/clk/loongson1/Makefile
index b7f6a16390e0..9240189183ff 100644
--- a/drivers/clk/loongson1/Makefile
+++ b/drivers/clk/loongson1/Makefile
@@ -1,3 +1,4 @@
-obj-y				+= clk.o
-obj-$(CONFIG_LOONGSON1_LS1B)	+= clk-loongson1b.o
-obj-$(CONFIG_LOONGSON1_LS1C)	+= clk-loongson1c.o
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_LOONGSON1_CLOCK_COMMON)	+= clk.o
+obj-$(CONFIG_LOONGSON1_CLOCK_LS1B)	+= clk-loongson1b.o
+obj-$(CONFIG_LOONGSON1_CLOCK_LS1C)	+= clk-loongson1c.o
-- 
2.20.1


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

* [PATCH v3 2/3] clk: loongson1: add of support
  2019-02-01  6:35   ` [PATCH v3 0/3] Enhance loongson-1 clock driver Jiaxun Yang
  2019-02-01  6:35     ` [PATCH v3 1/3] clk: loongson1: add configuration option for loongson1 clks Jiaxun Yang
@ 2019-02-01  6:35     ` Jiaxun Yang
  2019-02-06 19:16       ` Stephen Boyd
  2019-02-01  6:35     ` [PATCH v3 3/3] dt-bindings: clock: Add loongson-1 clock bindings Jiaxun Yang
  2 siblings, 1 reply; 16+ messages in thread
From: Jiaxun Yang @ 2019-02-01  6:35 UTC (permalink / raw)
  To: linux-mips
  Cc: mturquette, sboyd, linux-clk, linux-kernel, robh+dt,
	mark.rutland, devicetree, Jiaxun Yang

This patch add of support by split the clk_hw register and
clkdev register, then handle the of clk_hw via
of_clk_hw_onecell_get.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 drivers/clk/loongson1/clk-loongson1b.c | 197 ++++++++++++++++++++-----
 drivers/clk/loongson1/clk-loongson1c.c | 164 +++++++++++++++-----
 drivers/clk/loongson1/clk.c            |  47 +++++-
 drivers/clk/loongson1/clk.h            |  18 ++-
 4 files changed, 343 insertions(+), 83 deletions(-)

diff --git a/drivers/clk/loongson1/clk-loongson1b.c b/drivers/clk/loongson1/clk-loongson1b.c
index f36a97e993c0..2148df31db15 100644
--- a/drivers/clk/loongson1/clk-loongson1b.c
+++ b/drivers/clk/loongson1/clk-loongson1b.c
@@ -1,10 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2012-2016 Zhang, Keguang <keguang.zhang@gmail.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
+ * Copyright (c) 2019 Jiaxun Yang <jiaxun.yang@flygoat.com>
  */
 
 #include <linux/clkdev.h>
@@ -12,11 +9,41 @@
 #include <linux/io.h>
 #include <linux/err.h>
 
-#include <loongson1.h>
 #include "clk.h"
+#include <dt-bindings/clock/ls1b-clock.h>
+
+#define LS1B_CLK_COUNT	9
 
-#define OSC		(33 * 1000000)
 #define DIV_APB		2
+/* Clock PLL Divisor Register Bits */
+#define DIV_DC_EN			BIT(31)
+#define DIV_DC_RST			BIT(30)
+#define DIV_CPU_EN			BIT(25)
+#define DIV_CPU_RST			BIT(24)
+#define DIV_DDR_EN			BIT(19)
+#define DIV_DDR_RST			BIT(18)
+#define RST_DC_EN			BIT(5)
+#define RST_DC				BIT(4)
+#define RST_DDR_EN			BIT(3)
+#define RST_DDR				BIT(2)
+#define RST_CPU_EN			BIT(1)
+#define RST_CPU				BIT(0)
+
+#define DIV_DC_SHIFT			26
+#define DIV_CPU_SHIFT			20
+#define DIV_DDR_SHIFT			14
+
+#define DIV_DC_WIDTH			4
+#define DIV_CPU_WIDTH			4
+#define DIV_DDR_WIDTH			4
+
+#define BYPASS_DC_SHIFT			12
+#define BYPASS_DDR_SHIFT		10
+#define BYPASS_CPU_SHIFT		8
+
+#define BYPASS_DC_WIDTH			1
+#define BYPASS_DDR_WIDTH		1
+#define BYPASS_CPU_WIDTH		1
 
 static DEFINE_SPINLOCK(_lock);
 
@@ -25,9 +52,9 @@ static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw,
 {
 	u32 pll, rate;
 
-	pll = __raw_readl(LS1X_CLK_PLL_FREQ);
+	pll = __raw_readl(CLK_PLL_FREQ_ADDR);
 	rate = 12 + (pll & GENMASK(5, 0));
-	rate *= OSC;
+	rate *= parent_rate;
 	rate >>= 1;
 
 	return rate;
@@ -37,21 +64,29 @@ static const struct clk_ops ls1x_pll_clk_ops = {
 	.recalc_rate = ls1x_pll_recalc_rate,
 };
 
-static const char *const cpu_parents[] = { "cpu_clk_div", "osc_clk", };
-static const char *const ahb_parents[] = { "ahb_clk_div", "osc_clk", };
-static const char *const dc_parents[] = { "dc_clk_div", "osc_clk", };
 
-void __init ls1x_clk_init(void)
+struct clk_hw_onecell_data __init *ls1b_clk_init_hw(const char *osc_name)
 {
 	struct clk_hw *hw;
+	struct clk_hw_onecell_data *onecell;
+	const char *parents[2];
+
+	onecell = kzalloc(sizeof(*onecell) +
+			  (LS1B_CLK_COUNT * sizeof(struct clk_hw *)),
+			  GFP_KERNEL);
+
+	if (!onecell)
+		return NULL;
 
-	hw = clk_hw_register_fixed_rate(NULL, "osc_clk", NULL, 0, OSC);
-	clk_hw_register_clkdev(hw, "osc_clk", NULL);
+	onecell->num = LS1B_CLK_COUNT;
 
+	parents[1] = osc_name;
 	/* clock derived from 33 MHz OSC clk */
-	hw = clk_hw_register_pll(NULL, "pll_clk", "osc_clk",
+	hw = clk_hw_register_pll(NULL, "pll_clk", osc_name,
 				 &ls1x_pll_clk_ops, 0);
-	clk_hw_register_clkdev(hw, "pll_clk", NULL);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1B_CLK_PLL] = hw;
 
 	/* clock derived from PLL clk */
 	/*                                 _____
@@ -61,16 +96,22 @@ void __init ls1x_clk_init(void)
 	 *                                |_____|
 	 */
 	hw = clk_hw_register_divider(NULL, "cpu_clk_div", "pll_clk",
-				   CLK_GET_RATE_NOCACHE, LS1X_CLK_PLL_DIV,
+				   CLK_GET_RATE_NOCACHE, CLK_PLL_DIV_ADDR,
 				   DIV_CPU_SHIFT, DIV_CPU_WIDTH,
 				   CLK_DIVIDER_ONE_BASED |
 				   CLK_DIVIDER_ROUND_CLOSEST, &_lock);
-	clk_hw_register_clkdev(hw, "cpu_clk_div", NULL);
-	hw = clk_hw_register_mux(NULL, "cpu_clk", cpu_parents,
-			       ARRAY_SIZE(cpu_parents),
-			       CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV,
+	if (!hw)
+		goto err;
+	onecell->hws[LS1B_CLK_CPU_DIV] = hw;
+
+	parents[0] = "cpu_clk_div";
+	hw = clk_hw_register_mux(NULL, "cpu_clk", parents,
+			       ARRAY_SIZE(parents),
+			       CLK_SET_RATE_NO_REPARENT, CLK_PLL_DIV_ADDR,
 			       BYPASS_CPU_SHIFT, BYPASS_CPU_WIDTH, 0, &_lock);
-	clk_hw_register_clkdev(hw, "cpu_clk", NULL);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1B_CLK_CPU] = hw;
 
 	/*                                 _____
 	 *         _______________________|     |
@@ -79,14 +120,20 @@ void __init ls1x_clk_init(void)
 	 *                                |_____|
 	 */
 	hw = clk_hw_register_divider(NULL, "dc_clk_div", "pll_clk",
-				   0, LS1X_CLK_PLL_DIV, DIV_DC_SHIFT,
+				   0, CLK_PLL_DIV_ADDR, DIV_DC_SHIFT,
 				   DIV_DC_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock);
-	clk_hw_register_clkdev(hw, "dc_clk_div", NULL);
-	hw = clk_hw_register_mux(NULL, "dc_clk", dc_parents,
-			       ARRAY_SIZE(dc_parents),
-			       CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV,
+	if (!hw)
+		goto err;
+	onecell->hws[LS1B_CLK_DC_DIV] = hw;
+
+	parents[0] = "dc_clk_div";
+	hw = clk_hw_register_mux(NULL, "dc_clk", parents,
+			       ARRAY_SIZE(parents),
+			       CLK_SET_RATE_NO_REPARENT, CLK_PLL_DIV_ADDR,
 			       BYPASS_DC_SHIFT, BYPASS_DC_WIDTH, 0, &_lock);
-	clk_hw_register_clkdev(hw, "dc_clk", NULL);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1B_CLK_DC] = hw;
 
 	/*                                 _____
 	 *         _______________________|     |
@@ -94,23 +141,76 @@ void __init ls1x_clk_init(void)
 	 *        \___ PLL ___ DDR DIV ___|     |
 	 *                                |_____|
 	 */
-	hw = clk_hw_register_divider(NULL, "ahb_clk_div", "pll_clk",
-				   0, LS1X_CLK_PLL_DIV, DIV_DDR_SHIFT,
+	hw = clk_hw_register_divider(NULL, "ddr_clk_div", "pll_clk",
+				   0, CLK_PLL_DIV_ADDR, DIV_DDR_SHIFT,
 				   DIV_DDR_WIDTH, CLK_DIVIDER_ONE_BASED,
 				   &_lock);
-	clk_hw_register_clkdev(hw, "ahb_clk_div", NULL);
-	hw = clk_hw_register_mux(NULL, "ahb_clk", ahb_parents,
-			       ARRAY_SIZE(ahb_parents),
-			       CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV,
+	if (!hw)
+		goto err;
+	onecell->hws[LS1B_CLK_DDR_DIV] = hw;
+
+	parents[0] = "ddr_clk_div";
+	hw = clk_hw_register_mux(NULL, "ddr_clk", parents,
+			       ARRAY_SIZE(parents),
+			       CLK_SET_RATE_NO_REPARENT, CLK_PLL_DIV_ADDR,
 			       BYPASS_DDR_SHIFT, BYPASS_DDR_WIDTH, 0, &_lock);
-	clk_hw_register_clkdev(hw, "ahb_clk", NULL);
-	clk_hw_register_clkdev(hw, "ls1x-dma", NULL);
-	clk_hw_register_clkdev(hw, "stmmaceth", NULL);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1B_CLK_DDR] = hw;
+
+	hw = clk_hw_register_fixed_factor(NULL, "ahb_clk", "ddr_clk", 0, 1,
+					1);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1B_CLK_AHB] = hw;
 
 	/* clock derived from AHB clk */
 	/* APB clk is always half of the AHB clk */
 	hw = clk_hw_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1,
 					DIV_APB);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1B_CLK_APB] = hw;
+
+	return onecell;
+
+err:
+	kfree(onecell);
+	return NULL;
+}
+
+void __maybe_unused __init ls1b_register_clkdev(struct clk_hw_onecell_data *onecell)
+{
+	struct clk_hw *hw;
+
+	hw = onecell->hws[LS1B_CLK_PLL];
+	clk_hw_register_clkdev(hw, "pll_clk", NULL);
+
+	hw = onecell->hws[LS1B_CLK_CPU_DIV];
+	clk_hw_register_clkdev(hw, "cpu_clk_div", NULL);
+
+	hw = onecell->hws[LS1B_CLK_CPU];
+	clk_hw_register_clkdev(hw, "cpu_clk", NULL);
+
+
+	hw = onecell->hws[LS1B_CLK_DC_DIV];
+	clk_hw_register_clkdev(hw, "dc_clk_div", NULL);
+
+	hw = onecell->hws[LS1B_CLK_DC];
+	clk_hw_register_clkdev(hw, "dc_clk", NULL);
+
+	hw = onecell->hws[LS1B_CLK_DDR_DIV];
+	clk_hw_register_clkdev(hw, "ddr_clk_div", NULL);
+
+	hw = onecell->hws[LS1B_CLK_DDR];
+	clk_hw_register_clkdev(hw, "ddr_clk_div", NULL);
+
+	hw = onecell->hws[LS1B_CLK_AHB];
+	clk_hw_register_clkdev(hw, "ahb_clk", NULL);
+	clk_hw_register_clkdev(hw, "ls1x-dma", NULL);
+	clk_hw_register_clkdev(hw, "stmmaceth", NULL);
+
+	hw = onecell->hws[LS1B_CLK_APB];
 	clk_hw_register_clkdev(hw, "apb_clk", NULL);
 	clk_hw_register_clkdev(hw, "ls1x-ac97", NULL);
 	clk_hw_register_clkdev(hw, "ls1x-i2c", NULL);
@@ -120,3 +220,24 @@ void __init ls1x_clk_init(void)
 	clk_hw_register_clkdev(hw, "ls1x-wdt", NULL);
 	clk_hw_register_clkdev(hw, "serial8250", NULL);
 }
+
+static void __init ls1b_clk_of_setup(struct device_node *np)
+{
+	struct clk_hw_onecell_data *onecell;
+	int err;
+	const char *parent = of_clk_get_parent_name(np, 0);
+
+	clk_base = of_iomap(np, 0);
+
+	onecell = ls1b_clk_init_hw(parent);
+	if (!onecell)
+		pr_err("ls1b-clk: unable to register clk_hw");
+
+	err = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, onecell);
+	if (err)
+		pr_err("ls1b-clk: failed to add DT provider: %d\n", err);
+
+	pr_info("ls1b-clk: driver registered");
+}
+
+CLK_OF_DECLARE(clk_ls1b, "loongson,ls1b-clock", ls1b_clk_of_setup);
diff --git a/drivers/clk/loongson1/clk-loongson1c.c b/drivers/clk/loongson1/clk-loongson1c.c
index 3466f7320b40..076a2e1d5df9 100644
--- a/drivers/clk/loongson1/clk-loongson1c.c
+++ b/drivers/clk/loongson1/clk-loongson1c.c
@@ -1,21 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2016 Yang Ling <gnaygnil@gmail.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
+ * Copyright (c) 2012-2016 Zhang, Keguang <keguang.zhang@gmail.com>
+ * Copyright (c) 2019 Jiaxun Yang <jiaxun.yang@flygoat.com>
  */
 
 #include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 
-#include <loongson1.h>
 #include "clk.h"
 
-#define OSC		(24 * 1000000)
+#include <dt-bindings/clock/ls1c-clock.h>
+
+#define LS1C_CLK_COUNT	6
+
 #define DIV_APB		1
 
+/* PLL/SDRAM Frequency configuration register Bits */
+#define PLL_VALID			BIT(31)
+#define FRAC_N				GENMASK(23, 16)
+#define RST_TIME			GENMASK(3, 2)
+#define SDRAM_DIV			GENMASK(1, 0)
+
+/* CPU/CAMERA/DC Frequency configuration register Bits */
+#define DIV_DC_EN			BIT(31)
+#define DIV_DC				GENMASK(30, 24)
+#define DIV_CAM_EN			BIT(23)
+#define DIV_CAM				GENMASK(22, 16)
+#define DIV_CPU_EN			BIT(15)
+#define DIV_CPU				GENMASK(14, 8)
+#define DIV_DC_SEL_EN			BIT(5)
+#define DIV_DC_SEL			BIT(4)
+#define DIV_CAM_SEL_EN			BIT(3)
+#define DIV_CAM_SEL			BIT(2)
+#define DIV_CPU_SEL_EN			BIT(1)
+#define DIV_CPU_SEL			BIT(0)
+
+#define DIV_DC_SHIFT			24
+#define DIV_CAM_SHIFT			16
+#define DIV_CPU_SHIFT			8
+#define DIV_DDR_SHIFT			0
+
+#define DIV_DC_WIDTH			7
+#define DIV_CAM_WIDTH			7
+#define DIV_CPU_WIDTH			7
+#define DIV_DDR_WIDTH			2
+
 static DEFINE_SPINLOCK(_lock);
 
 static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw,
@@ -23,9 +52,9 @@ static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw,
 {
 	u32 pll, rate;
 
-	pll = __raw_readl(LS1X_CLK_PLL_FREQ);
+	pll = __raw_readl(CLK_PLL_FREQ_ADDR);
 	rate = ((pll >> 8) & 0xff) + ((pll >> 16) & 0xff);
-	rate *= OSC;
+	rate *= parent_rate;
 	rate >>= 2;
 
 	return rate;
@@ -42,50 +71,95 @@ static const struct clk_div_table ahb_div_table[] = {
 	[3] = { .val = 3, .div = 3 },
 };
 
-void __init ls1x_clk_init(void)
+struct clk_hw_onecell_data __init *ls1c_clk_init_hw(const char *osc_name)
 {
 	struct clk_hw *hw;
+	struct clk_hw_onecell_data *onecell;
+
+	onecell = kzalloc(sizeof(*onecell) +
+			  (LS1C_CLK_COUNT * sizeof(struct clk_hw *)),
+			  GFP_KERNEL);
+
+	if (!onecell)
+		return NULL;
 
-	hw = clk_hw_register_fixed_rate(NULL, "osc_clk", NULL, 0, OSC);
-	clk_hw_register_clkdev(hw, "osc_clk", NULL);
+	onecell->num = LS1C_CLK_COUNT;
 
-	/* clock derived from 24 MHz OSC clk */
-	hw = clk_hw_register_pll(NULL, "pll_clk", "osc_clk",
+	/* clock derived from OSC clk */
+	hw = clk_hw_register_pll(NULL, "pll_clk", osc_name,
 				&ls1x_pll_clk_ops, 0);
-	clk_hw_register_clkdev(hw, "pll_clk", NULL);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1C_CLK_PLL] = hw;
 
-	hw = clk_hw_register_divider(NULL, "cpu_clk_div", "pll_clk",
-				   CLK_GET_RATE_NOCACHE, LS1X_CLK_PLL_DIV,
+	hw = clk_hw_register_divider(NULL, "cpu_clk", "pll_clk",
+				   CLK_GET_RATE_NOCACHE, CLK_PLL_DIV_ADDR,
 				   DIV_CPU_SHIFT, DIV_CPU_WIDTH,
 				   CLK_DIVIDER_ONE_BASED |
 				   CLK_DIVIDER_ROUND_CLOSEST, &_lock);
-	clk_hw_register_clkdev(hw, "cpu_clk_div", NULL);
-	hw = clk_hw_register_fixed_factor(NULL, "cpu_clk", "cpu_clk_div",
-					0, 1, 1);
-	clk_hw_register_clkdev(hw, "cpu_clk", NULL);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1C_CLK_CPU] = hw;
 
-	hw = clk_hw_register_divider(NULL, "dc_clk_div", "pll_clk",
-				   0, LS1X_CLK_PLL_DIV, DIV_DC_SHIFT,
+
+	hw = clk_hw_register_divider(NULL, "dc_clk", "pll_clk",
+				   0, CLK_PLL_DIV_ADDR, DIV_DC_SHIFT,
 				   DIV_DC_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock);
-	clk_hw_register_clkdev(hw, "dc_clk_div", NULL);
-	hw = clk_hw_register_fixed_factor(NULL, "dc_clk", "dc_clk_div",
-					0, 1, 1);
-	clk_hw_register_clkdev(hw, "dc_clk", NULL);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1C_CLK_DC] = hw;
 
-	hw = clk_hw_register_divider_table(NULL, "ahb_clk_div", "cpu_clk_div",
-				0, LS1X_CLK_PLL_FREQ, DIV_DDR_SHIFT,
+	hw = clk_hw_register_divider_table(NULL, "ddr_clk", "cpu_clk",
+				0, CLK_PLL_FREQ_ADDR, DIV_DDR_SHIFT,
 				DIV_DDR_WIDTH, CLK_DIVIDER_ALLOW_ZERO,
 				ahb_div_table, &_lock);
-	clk_hw_register_clkdev(hw, "ahb_clk_div", NULL);
-	hw = clk_hw_register_fixed_factor(NULL, "ahb_clk", "ahb_clk_div",
+	if (!hw)
+		goto err;
+	onecell->hws[LS1C_CLK_DDR] = hw;
+
+
+	hw = clk_hw_register_fixed_factor(NULL, "ahb_clk", "ddr_clk",
 					0, 1, 1);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1C_CLK_AHB] = hw;
+
+
+	hw = clk_hw_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1,
+					DIV_APB);
+	if (!hw)
+		goto err;
+	onecell->hws[LS1C_CLK_APB] = hw;
+
+	return onecell;
+
+err:
+	kfree(onecell);
+	return NULL;
+}
+
+void __maybe_unused __init ls1c_register_clkdev(struct clk_hw_onecell_data *onecell)
+{
+	struct clk_hw *hw;
+
+	hw = onecell->hws[LS1C_CLK_PLL];
+	clk_hw_register_clkdev(hw, "pll_clk", NULL);
+
+	hw = onecell->hws[LS1C_CLK_CPU];
+	clk_hw_register_clkdev(hw, "cpu_clk", NULL);
+
+	hw = onecell->hws[LS1C_CLK_DC];
+	clk_hw_register_clkdev(hw, "dc_clk", NULL);
+
+	hw = onecell->hws[LS1C_CLK_DDR];
+	clk_hw_register_clkdev(hw, "ddr_clk", NULL);
+
+	hw = onecell->hws[LS1C_CLK_AHB];
 	clk_hw_register_clkdev(hw, "ahb_clk", NULL);
 	clk_hw_register_clkdev(hw, "ls1x-dma", NULL);
 	clk_hw_register_clkdev(hw, "stmmaceth", NULL);
 
-	/* clock derived from AHB clk */
-	hw = clk_hw_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1,
-					DIV_APB);
+	hw = onecell->hws[LS1C_CLK_APB];
 	clk_hw_register_clkdev(hw, "apb_clk", NULL);
 	clk_hw_register_clkdev(hw, "ls1x-ac97", NULL);
 	clk_hw_register_clkdev(hw, "ls1x-i2c", NULL);
@@ -95,3 +169,23 @@ void __init ls1x_clk_init(void)
 	clk_hw_register_clkdev(hw, "ls1x-wdt", NULL);
 	clk_hw_register_clkdev(hw, "serial8250", NULL);
 }
+
+static void __init ls1c_clk_of_setup(struct device_node *np)
+{
+	struct clk_hw_onecell_data *onecell;
+	int err;
+	const char *parent = of_clk_get_parent_name(np, 0);
+
+	clk_base = of_iomap(np, 0);
+
+	onecell = ls1c_clk_init_hw(parent);
+	if (!onecell)
+		pr_err("ls1c-clk: unable to register clk_hw");
+
+	err = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, onecell);
+	if (err)
+		pr_err("ls1c-clk: failed to add DT provider: %d\n", err);
+
+	pr_info("ls1c-clk: driver registered");
+}
+CLK_OF_DECLARE(clk_ls1c, "loongson,ls1c-clock", ls1c_clk_of_setup);
diff --git a/drivers/clk/loongson1/clk.c b/drivers/clk/loongson1/clk.c
index 983ce9f6edbb..b4dc7dd8e0cd 100644
--- a/drivers/clk/loongson1/clk.c
+++ b/drivers/clk/loongson1/clk.c
@@ -1,14 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2012-2016 Zhang, Keguang <keguang.zhang@gmail.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
+ * Copyright (c) 2019 Jiaxun Yang <jiaxun.yang@flygoat.com>
  */
 
+#include <linux/clkdev.h>
+
 #include <linux/clk-provider.h>
 #include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+
+#include <asm/mach-loongson32/platform.h>
+
+void __iomem *clk_base;
+
+#define LS1C_OSC		(24 * 1000000)
+#define LS1B_OSC		(33 * 1000000)
+
+#define LS1X_CLK_BASE	0x1fe78030
 
 #include "clk.h"
 
@@ -43,3 +53,30 @@ struct clk_hw *__init clk_hw_register_pll(struct device *dev,
 
 	return hw;
 }
+
+void __init ls1x_clk_init(void)
+{
+	struct clk_hw *hw;
+	struct clk_hw_onecell_data *onecell;
+
+	clk_base = (void __iomem *)KSEG1ADDR(LS1X_CLK_BASE);
+#ifdef CONFIG_LOONGSON1_LS1B
+	hw = clk_hw_register_fixed_rate(NULL, "osc_clk", NULL, 0, LS1B_OSC);
+	clk_hw_register_clkdev(hw, "osc_clk", NULL);
+	onecell = ls1c_clk_init_hw("osc_clk");
+	if (!onecell)
+		panic("ls1x-clk: unable to register clk_hw");
+
+	ls1c_register_clkdev(onecell);
+#elif defined(CONFIG_LOONGSON1_LS1C)
+	hw = clk_hw_register_fixed_rate(NULL, "osc_clk", NULL, 0, LS1C_OSC);
+	clk_hw_register_clkdev(hw, "osc_clk", NULL);
+	onecell = ls1c_clk_init_hw("osc_clk");
+	if (!onecell)
+		panic("ls1x-clk: unable to register clk_hw");
+
+	ls1c_register_clkdev(onecell);
+#else
+	panic("ls1x-clk: not loongson platform");
+#endif
+}
diff --git a/drivers/clk/loongson1/clk.h b/drivers/clk/loongson1/clk.h
index 085d74b5d496..be7cc72c0ea3 100644
--- a/drivers/clk/loongson1/clk.h
+++ b/drivers/clk/loongson1/clk.h
@@ -1,10 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2012-2016 Zhang, Keguang <keguang.zhang@gmail.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
+ * Copyright (c) 2019 Jiaxun Yang <jiaxun.yang@flygoat.com>
  */
 
 #ifndef __LOONGSON1_CLK_H
@@ -16,4 +13,15 @@ struct clk_hw *clk_hw_register_pll(struct device *dev,
 				   const struct clk_ops *ops,
 				   unsigned long flags);
 
+struct clk_hw_onecell_data __init *ls1c_clk_init_hw(const char *osc_name);
+struct clk_hw_onecell_data __init *ls1b_clk_init_hw(const char *osc_name);
+
+void __maybe_unused __init ls1c_register_clkdev(struct clk_hw_onecell_data *onecell);
+void __maybe_unused __init ls1b_register_clkdev(struct clk_hw_onecell_data *onecell);
+
+extern void __iomem *clk_base;
+
+#define CLK_PLL_FREQ_ADDR	clk_base
+#define CLK_PLL_DIV_ADDR	(clk_base + 0x4)
+
 #endif /* __LOONGSON1_CLK_H */
-- 
2.20.1


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

* [PATCH v3 3/3] dt-bindings: clock: Add loongson-1 clock bindings
  2019-02-01  6:35   ` [PATCH v3 0/3] Enhance loongson-1 clock driver Jiaxun Yang
  2019-02-01  6:35     ` [PATCH v3 1/3] clk: loongson1: add configuration option for loongson1 clks Jiaxun Yang
  2019-02-01  6:35     ` [PATCH v3 2/3] clk: loongson1: add of support Jiaxun Yang
@ 2019-02-01  6:35     ` Jiaxun Yang
  2019-02-13 22:56       ` Rob Herring
  2 siblings, 1 reply; 16+ messages in thread
From: Jiaxun Yang @ 2019-02-01  6:35 UTC (permalink / raw)
  To: linux-mips
  Cc: mturquette, sboyd, linux-clk, linux-kernel, robh+dt,
	mark.rutland, devicetree, Jiaxun Yang

Loongson-1 is a series of MIPS MCUs.
This patch add the clock bindings for loongson-1b and
loongson-1c clock subsystem.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 .../bindings/clock/loongson1-clock.txt          | 14 ++++++++++++++
 include/dt-bindings/clock/ls1b-clock.h          | 17 +++++++++++++++++
 include/dt-bindings/clock/ls1c-clock.h          | 14 ++++++++++++++
 3 files changed, 45 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/loongson1-clock.txt
 create mode 100644 include/dt-bindings/clock/ls1b-clock.h
 create mode 100644 include/dt-bindings/clock/ls1c-clock.h

diff --git a/Documentation/devicetree/bindings/clock/loongson1-clock.txt b/Documentation/devicetree/bindings/clock/loongson1-clock.txt
new file mode 100644
index 000000000000..5afd13a98eaa
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/loongson1-clock.txt
@@ -0,0 +1,14 @@
+* Clock bindings for Loongson-1 MCUs
+
+Required properties:
+- compatible: must contain one of the following compatibles:
+                - "loongson,ls1b-clock"
+                - "loongson,ls1c-clock"
+
+- reg: Address and length of the register set
+- #clock-cells: Should be <1>
+- clocks: list of input clocks
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell. See include/dt-bindings/clock/ls1c-clock.h
+or include/dt-bindings/clock/ls1b-clock.h for the full list of clocks.
diff --git a/include/dt-bindings/clock/ls1b-clock.h b/include/dt-bindings/clock/ls1b-clock.h
new file mode 100644
index 000000000000..c7ae85bb4583
--- /dev/null
+++ b/include/dt-bindings/clock/ls1b-clock.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2019 Jiaxun Yang <jiaxun.yang@flygoat.com> */
+
+#ifndef __DT_BINDINGS_CLOCK_LS1B_CLOCK_H__
+#define __DT_BINDINGS_CLOCK_LS1B_CLOCK_H__
+
+#define LS1B_CLK_PLL 0
+#define LS1B_CLK_CPU_DIV 1
+#define LS1B_CLK_CPU 2
+#define LS1B_CLK_DC_DIV 3
+#define LS1B_CLK_DC 4
+#define LS1B_CLK_DDR_DIV 5
+#define LS1B_CLK_DDR 6
+#define LS1B_CLK_AHB 7
+#define LS1B_CLK_APB 8
+
+#endif /* __DT_BINDINGS_CLOCK_LS1B_CLOCK_H__ */
diff --git a/include/dt-bindings/clock/ls1c-clock.h b/include/dt-bindings/clock/ls1c-clock.h
new file mode 100644
index 000000000000..9d01914f374e
--- /dev/null
+++ b/include/dt-bindings/clock/ls1c-clock.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2019 Jiaxun Yang <jiaxun.yang@flygoat.com> */
+
+#ifndef __DT_BINDINGS_CLOCK_LS1C_CLOCK_H__
+#define __DT_BINDINGS_CLOCK_LS1C_CLOCK_H__
+
+#define LS1C_CLK_PLL 0
+#define LS1C_CLK_CPU 1
+#define LS1C_CLK_DC 2
+#define LS1C_CLK_DDR 3
+#define LS1C_CLK_AHB 4
+#define LS1C_CLK_APB 5
+
+#endif /* __DT_BINDINGS_CLOCK_LS1C_CLOCK_H__ */
-- 
2.20.1


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

* Re: [PATCH v3 2/3] clk: loongson1: add of support
  2019-02-01  6:35     ` [PATCH v3 2/3] clk: loongson1: add of support Jiaxun Yang
@ 2019-02-06 19:16       ` Stephen Boyd
  0 siblings, 0 replies; 16+ messages in thread
From: Stephen Boyd @ 2019-02-06 19:16 UTC (permalink / raw)
  To: Jiaxun Yang, linux-mips
  Cc: mturquette, linux-clk, linux-kernel, robh+dt, mark.rutland,
	devicetree, Jiaxun Yang

Quoting Jiaxun Yang (2019-01-31 22:35:39)
> This patch add of support by split the clk_hw register and
> clkdev register, then handle the of clk_hw via
> of_clk_hw_onecell_get.
> 
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>

Why though? There isn't any motivation here.

> ---
>  drivers/clk/loongson1/clk-loongson1b.c | 197 ++++++++++++++++++++-----
>  drivers/clk/loongson1/clk-loongson1c.c | 164 +++++++++++++++-----
>  drivers/clk/loongson1/clk.c            |  47 +++++-
>  drivers/clk/loongson1/clk.h            |  18 ++-
>  4 files changed, 343 insertions(+), 83 deletions(-)

It just looks like more lines are added.

> 
> diff --git a/drivers/clk/loongson1/clk-loongson1b.c b/drivers/clk/loongson1/clk-loongson1b.c
> index f36a97e993c0..2148df31db15 100644
> --- a/drivers/clk/loongson1/clk-loongson1b.c
> +++ b/drivers/clk/loongson1/clk-loongson1b.c
> @@ -1,10 +1,7 @@
> +// SPDX-License-Identifier: GPL-2.0
>  /*
>   * Copyright (c) 2012-2016 Zhang, Keguang <keguang.zhang@gmail.com>
> - *
> - * This program is free software; you can redistribute  it and/or modify it
> - * under  the terms of  the GNU General  Public License as published by the
> - * Free Software Foundation;  either version 2 of the  License, or (at your
> - * option) any later version.

Please make SPDX change in another patch.

> + * Copyright (c) 2019 Jiaxun Yang <jiaxun.yang@flygoat.com>
>   */
>  
>  #include <linux/clkdev.h>
> @@ -12,11 +9,41 @@
>  #include <linux/io.h>
>  #include <linux/err.h>
>  
> -#include <loongson1.h>
>  #include "clk.h"
> +#include <dt-bindings/clock/ls1b-clock.h>
> +
> +#define LS1B_CLK_COUNT 9
>  
> -#define OSC            (33 * 1000000)
>  #define DIV_APB                2
> +/* Clock PLL Divisor Register Bits */
> +#define DIV_DC_EN                      BIT(31)
> +#define DIV_DC_RST                     BIT(30)
> +#define DIV_CPU_EN                     BIT(25)
> +#define DIV_CPU_RST                    BIT(24)
> +#define DIV_DDR_EN                     BIT(19)
> +#define DIV_DDR_RST                    BIT(18)
> +#define RST_DC_EN                      BIT(5)
> +#define RST_DC                         BIT(4)
> +#define RST_DDR_EN                     BIT(3)
> +#define RST_DDR                                BIT(2)
> +#define RST_CPU_EN                     BIT(1)
> +#define RST_CPU                                BIT(0)
> +
> +#define DIV_DC_SHIFT                   26
> +#define DIV_CPU_SHIFT                  20
> +#define DIV_DDR_SHIFT                  14
> +
> +#define DIV_DC_WIDTH                   4
> +#define DIV_CPU_WIDTH                  4
> +#define DIV_DDR_WIDTH                  4
> +
> +#define BYPASS_DC_SHIFT                        12
> +#define BYPASS_DDR_SHIFT               10
> +#define BYPASS_CPU_SHIFT               8
> +
> +#define BYPASS_DC_WIDTH                        1
> +#define BYPASS_DDR_WIDTH               1
> +#define BYPASS_CPU_WIDTH               1
>  
>  static DEFINE_SPINLOCK(_lock);
>  
> @@ -25,9 +52,9 @@ static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw,
>  {
>         u32 pll, rate;
>  
> -       pll = __raw_readl(LS1X_CLK_PLL_FREQ);
> +       pll = __raw_readl(CLK_PLL_FREQ_ADDR);
>         rate = 12 + (pll & GENMASK(5, 0));
> -       rate *= OSC;
> +       rate *= parent_rate;
>         rate >>= 1;
>  
>         return rate;

IS this change related? Maybe think about splitting this out too and
just have a patch that re-does all the registration calls in one patch.

> @@ -120,3 +220,24 @@ void __init ls1x_clk_init(void)
>         clk_hw_register_clkdev(hw, "ls1x-wdt", NULL);
>         clk_hw_register_clkdev(hw, "serial8250", NULL);
>  }
> +
> +static void __init ls1b_clk_of_setup(struct device_node *np)
> +{
> +       struct clk_hw_onecell_data *onecell;
> +       int err;
> +       const char *parent = of_clk_get_parent_name(np, 0);
> +
> +       clk_base = of_iomap(np, 0);
> +
> +       onecell = ls1b_clk_init_hw(parent);
> +       if (!onecell)
> +               pr_err("ls1b-clk: unable to register clk_hw");
> +
> +       err = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, onecell);
> +       if (err)
> +               pr_err("ls1b-clk: failed to add DT provider: %d\n", err);
> +
> +       pr_info("ls1b-clk: driver registered");

Please no "I'm alive!" messages (plus it's missing a newline at the
end). At the least, make them pr_debug() level.

> +}
> +
> +CLK_OF_DECLARE(clk_ls1b, "loongson,ls1b-clock", ls1b_clk_of_setup);
> diff --git a/drivers/clk/loongson1/clk.c b/drivers/clk/loongson1/clk.c
> index 983ce9f6edbb..b4dc7dd8e0cd 100644
> --- a/drivers/clk/loongson1/clk.c
> +++ b/drivers/clk/loongson1/clk.c
> @@ -1,14 +1,24 @@
> +// SPDX-License-Identifier: GPL-2.0
>  /*
>   * Copyright (c) 2012-2016 Zhang, Keguang <keguang.zhang@gmail.com>
> - *
> - * This program is free software; you can redistribute  it and/or modify it
> - * under  the terms of  the GNU General  Public License as published by the
> - * Free Software Foundation;  either version 2 of the  License, or (at your
> - * option) any later version.
> + * Copyright (c) 2019 Jiaxun Yang <jiaxun.yang@flygoat.com>
>   */
>  
> +#include <linux/clkdev.h>
> +
>  #include <linux/clk-provider.h>
>  #include <linux/slab.h>
> +#include <linux/io.h>
> +#include <linux/of_address.h>
> +
> +#include <asm/mach-loongson32/platform.h>
> +
> +void __iomem *clk_base;
> +
> +#define LS1C_OSC               (24 * 1000000)
> +#define LS1B_OSC               (33 * 1000000)
> +
> +#define LS1X_CLK_BASE  0x1fe78030
>  
>  #include "clk.h"
>  
> @@ -43,3 +53,30 @@ struct clk_hw *__init clk_hw_register_pll(struct device *dev,
>  
>         return hw;
>  }
> +
> +void __init ls1x_clk_init(void)
> +{
> +       struct clk_hw *hw;
> +       struct clk_hw_onecell_data *onecell;
> +
> +       clk_base = (void __iomem *)KSEG1ADDR(LS1X_CLK_BASE);
> +#ifdef CONFIG_LOONGSON1_LS1B
> +       hw = clk_hw_register_fixed_rate(NULL, "osc_clk", NULL, 0, LS1B_OSC);
> +       clk_hw_register_clkdev(hw, "osc_clk", NULL);
> +       onecell = ls1c_clk_init_hw("osc_clk");
> +       if (!onecell)
> +               panic("ls1x-clk: unable to register clk_hw");
> +
> +       ls1c_register_clkdev(onecell);

Should be ls1b_register_clkdev?

> +#elif defined(CONFIG_LOONGSON1_LS1C)
> +       hw = clk_hw_register_fixed_rate(NULL, "osc_clk", NULL, 0, LS1C_OSC);
> +       clk_hw_register_clkdev(hw, "osc_clk", NULL);
> +       onecell = ls1c_clk_init_hw("osc_clk");
> +       if (!onecell)
> +               panic("ls1x-clk: unable to register clk_hw");
> +
> +       ls1c_register_clkdev(onecell);
> +#else
> +       panic("ls1x-clk: not loongson platform");
> +#endif

Can this be implemented with if (IS_ENABLED(CONFIG_LOONGSON1_LS1B))
else-if, etc.? That would make the maybe unused attribute unnecessary and
provide more compile time coverage.

Also, a lot of the code is duplicated twice so that could all be
collapsed together and then the only difference is the fixed rate and
the registration function at the end? 

Or can this just be implemented in the 1b and 1c files instead of in
some common place here?

> +}
> diff --git a/drivers/clk/loongson1/clk.h b/drivers/clk/loongson1/clk.h
> index 085d74b5d496..be7cc72c0ea3 100644
> --- a/drivers/clk/loongson1/clk.h
> +++ b/drivers/clk/loongson1/clk.h
> @@ -16,4 +13,15 @@ struct clk_hw *clk_hw_register_pll(struct device *dev,
>                                    const struct clk_ops *ops,
>                                    unsigned long flags);
>  
> +struct clk_hw_onecell_data __init *ls1c_clk_init_hw(const char *osc_name);
> +struct clk_hw_onecell_data __init *ls1b_clk_init_hw(const char *osc_name);
> +
> +void __maybe_unused __init ls1c_register_clkdev(struct clk_hw_onecell_data *onecell);
> +void __maybe_unused __init ls1b_register_clkdev(struct clk_hw_onecell_data *onecell);

I doubt that __maybe_unused and __init are needed here in the header
file. Just on the actual implementation of the function.


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

* Re: [PATCH v3 1/3] clk: loongson1: add configuration option for loongson1 clks
  2019-02-01  6:35     ` [PATCH v3 1/3] clk: loongson1: add configuration option for loongson1 clks Jiaxun Yang
@ 2019-02-06 19:18       ` Stephen Boyd
  0 siblings, 0 replies; 16+ messages in thread
From: Stephen Boyd @ 2019-02-06 19:18 UTC (permalink / raw)
  To: Jiaxun Yang, linux-mips
  Cc: mturquette, linux-clk, linux-kernel, robh+dt, mark.rutland,
	devicetree, Jiaxun Yang

Quoting Jiaxun Yang (2019-01-31 22:35:38)
> diff --git a/drivers/clk/loongson1/Kconfig b/drivers/clk/loongson1/Kconfig
> new file mode 100644
> index 000000000000..e2220332d797
> --- /dev/null
> +++ b/drivers/clk/loongson1/Kconfig
> @@ -0,0 +1,27 @@
> +menu "Loongson-1 Clock drivers"
> +       depends on MACH_LOONGSON32
> +
> +config LOONGSON1_CLOCK_COMMON
> +       bool
> +
> +config LOONGSON1_CLOCK_LS1B
> +       bool "Loongson 1B driver"
> +       default y

Should be default CONFIG_LOONGSON1_LS1B?
> +       select LOONGSON1_CLOCK_COMMON

Drop the selects and have the menuconfig make the "COMMON" config option
enabled then?

> +       help
> +         Support the clocks provided by the clock hardware on Loongson-1B
> +         and compatible SoCs.
> +
> +         If building for a Loongson-1B SoC, you want to say Y here.
> +
> +config LOONGSON1_CLOCK_LS1C
> +       bool "Loongson 1C driver"
> +       default y

And default CONFIG_LOONGSON1_LS1C?

> +       select LOONGSON1_CLOCK_COMMON
> +       help
> +         Support the clocks provided by the clock hardware on Loongson-1C
> +         and compatible SoCs.
> +
> +         If building for a Loongson-1C SoC, you want to say Y here.
> +
> +endmenu

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

* Re: [PATCH v3 3/3] dt-bindings: clock: Add loongson-1 clock bindings
  2019-02-01  6:35     ` [PATCH v3 3/3] dt-bindings: clock: Add loongson-1 clock bindings Jiaxun Yang
@ 2019-02-13 22:56       ` Rob Herring
  0 siblings, 0 replies; 16+ messages in thread
From: Rob Herring @ 2019-02-13 22:56 UTC (permalink / raw)
  To: Jiaxun Yang
  Cc: linux-mips, mturquette, sboyd, linux-clk, linux-kernel, robh+dt,
	mark.rutland, devicetree, Jiaxun Yang

On Fri,  1 Feb 2019 14:35:40 +0800, Jiaxun Yang wrote:
> Loongson-1 is a series of MIPS MCUs.
> This patch add the clock bindings for loongson-1b and
> loongson-1c clock subsystem.
> 
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
>  .../bindings/clock/loongson1-clock.txt          | 14 ++++++++++++++
>  include/dt-bindings/clock/ls1b-clock.h          | 17 +++++++++++++++++
>  include/dt-bindings/clock/ls1c-clock.h          | 14 ++++++++++++++
>  3 files changed, 45 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/loongson1-clock.txt
>  create mode 100644 include/dt-bindings/clock/ls1b-clock.h
>  create mode 100644 include/dt-bindings/clock/ls1c-clock.h
> 

Reviewed-by: Rob Herring <robh@kernel.org>

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

end of thread, back to index

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-25 13:34 [PATCH 0/3] Enhance loongson-1 clock driver Jiaxun Yang
2019-01-25 13:34 ` [PATCH 1/3] clk: loongson1: add configuration option for loongson1 clks Jiaxun Yang
2019-01-25 13:34 ` [PATCH 2/3] clk: loongson1: add of support Jiaxun Yang
2019-01-25 13:34 ` [PATCH 3/3] dt-bindings: clock: Add loongson-1 clock bindings Jiaxun Yang
2019-01-28 15:20 ` [PATCH 0/3] Enhance loongson-1 clock driver Jiaxun Yang
2019-01-28 15:20   ` [PATCH v2 1/3] clk: loongson1: add configuration option for loongson1 clks Jiaxun Yang
2019-01-28 15:20   ` [PATCH v2 2/3] clk: loongson1: add of support Jiaxun Yang
2019-01-28 15:20   ` [PATCH v2 3/3] dt-bindings: clock: Add loongson-1 clock bindings Jiaxun Yang
2019-01-30 19:47     ` Rob Herring
2019-02-01  6:35   ` [PATCH v3 0/3] Enhance loongson-1 clock driver Jiaxun Yang
2019-02-01  6:35     ` [PATCH v3 1/3] clk: loongson1: add configuration option for loongson1 clks Jiaxun Yang
2019-02-06 19:18       ` Stephen Boyd
2019-02-01  6:35     ` [PATCH v3 2/3] clk: loongson1: add of support Jiaxun Yang
2019-02-06 19:16       ` Stephen Boyd
2019-02-01  6:35     ` [PATCH v3 3/3] dt-bindings: clock: Add loongson-1 clock bindings Jiaxun Yang
2019-02-13 22:56       ` Rob Herring

Linux-Clk Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-clk/0 linux-clk/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-clk linux-clk/ https://lore.kernel.org/linux-clk \
		linux-clk@vger.kernel.org linux-clk@archiver.kernel.org
	public-inbox-index linux-clk


Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-clk


AGPL code for this site: git clone https://public-inbox.org/ public-inbox