All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v10 1/4] dt-bindings: clock: add loongson-2 clock include file
@ 2022-11-29  3:41 Yinbo Zhu
  2022-11-29  3:41 ` [PATCH v10 2/4] clk: clk-loongson2: add clock controller driver support Yinbo Zhu
                   ` (3 more replies)
  0 siblings, 4 replies; 24+ messages in thread
From: Yinbo Zhu @ 2022-11-29  3:41 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rob Herring,
	Krzysztof Kozlowski, Huacai Chen, WANG Xuerui, Jiaxun Yang,
	Jianmin Lv, Yang Li, linux-clk, devicetree, linux-kernel,
	loongarch, Yinbo Zhu
  Cc: Krzysztof Kozlowski

This file defines all Loongson-2 SoC clock indexes, it should be
included in the device tree in which there's device using the
clocks.

Signed-off-by: Yinbo Zhu <zhuyinbo@loongson.cn>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
Change in v10:
		1. NO change, but other patch in this series of patches has
		   changes.
Change in v9:
		1. Add all history changelog infomation.
Change in v8:
		1. NO change, but other patch in this series of patches has
		   changes.
Change in v7:
		1. NO change, but other patch in this series of patches has
		   changes.
Change in v6:
		1. Replace string LOONGSON2 with LOONGSON-2 in MAINTAINERS.
Change in v5:
		1. Replace loongson2/Loongson2 with loongson-2/Loongson-2.
		2. Replace soc with SoC.
Change in v4:
		1. NO change, but other patch in this series of patches has
		   changes.
Change in v3:
		1. Add the review information.
Change in v2:
		1. Make filename matching the compatible.
		2. Drop weird indentation after define.
		3. Add dual license.
		4. Use subject prefixes matching the subsystem.

 MAINTAINERS                                   |  6 ++++
 include/dt-bindings/clock/loongson,ls2k-clk.h | 29 +++++++++++++++++++
 2 files changed, 35 insertions(+)
 create mode 100644 include/dt-bindings/clock/loongson,ls2k-clk.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 182129c73ed5..ab94893fe2f6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12021,6 +12021,12 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml
 F:	drivers/thermal/loongson2_thermal.c
 
+LOONGSON-2 SOC SERIES CLOCK DRIVER
+M:	Yinbo Zhu <zhuyinbo@loongson.cn>
+L:	linux-clk@vger.kernel.org
+S:	Maintained
+F:	include/dt-bindings/clock/loongson,ls2k-clk.h
+
 LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
 M:	Sathya Prakash <sathya.prakash@broadcom.com>
 M:	Sreekanth Reddy <sreekanth.reddy@broadcom.com>
diff --git a/include/dt-bindings/clock/loongson,ls2k-clk.h b/include/dt-bindings/clock/loongson,ls2k-clk.h
new file mode 100644
index 000000000000..db1e27e792ff
--- /dev/null
+++ b/include/dt-bindings/clock/loongson,ls2k-clk.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Author: Yinbo Zhu <zhuyinbo@loongson.cn>
+ * Copyright (C) 2022-2023 Loongson Technology Corporation Limited
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_LOONGSON2_H
+#define __DT_BINDINGS_CLOCK_LOONGSON2_H
+
+#define LOONGSON2_REF_100M				0
+#define LOONGSON2_NODE_PLL				1
+#define LOONGSON2_DDR_PLL				2
+#define LOONGSON2_DC_PLL				3
+#define LOONGSON2_PIX0_PLL				4
+#define LOONGSON2_PIX1_PLL				5
+#define LOONGSON2_NODE_CLK				6
+#define LOONGSON2_HDA_CLK				7
+#define LOONGSON2_GPU_CLK				8
+#define LOONGSON2_DDR_CLK				9
+#define LOONGSON2_GMAC_CLK				10
+#define LOONGSON2_DC_CLK				11
+#define LOONGSON2_APB_CLK				12
+#define LOONGSON2_USB_CLK				13
+#define LOONGSON2_SATA_CLK				14
+#define LOONGSON2_PIX0_CLK				15
+#define LOONGSON2_PIX1_CLK				16
+#define LOONGSON2_CLK_END				17
+
+#endif
-- 
2.31.1


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

* [PATCH v10 2/4] clk: clk-loongson2: add clock controller driver support
  2022-11-29  3:41 [PATCH v10 1/4] dt-bindings: clock: add loongson-2 clock include file Yinbo Zhu
@ 2022-11-29  3:41 ` Yinbo Zhu
  2022-11-30  3:32   ` XiaochuanMao
                     ` (5 more replies)
  2022-11-29  3:41 ` [PATCH v10 3/4] LoongArch: time: add of_clk_init in time_init Yinbo Zhu
                   ` (2 subsequent siblings)
  3 siblings, 6 replies; 24+ messages in thread
From: Yinbo Zhu @ 2022-11-29  3:41 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rob Herring,
	Krzysztof Kozlowski, Huacai Chen, WANG Xuerui, Jiaxun Yang,
	Jianmin Lv, Yang Li, linux-clk, devicetree, linux-kernel,
	loongarch, Yinbo Zhu

This driver provides support for clock controller on Loongson-2 SoC,
the Loongson-2 SoC uses a 100MHz clock as the PLL reference clock,
there are five independent PLLs inside, each of which PLL can
provide up to three sets of frequency dependent clock outputs.

Signed-off-by: Yinbo Zhu <zhuyinbo@loongson.cn>
---
Change in v10:
		1. Detach of_clk_init to another patch. 
Change in v9:
		1. Add all history changelog information.
Change in v8:
		1. Remove the flag "CLK_IS_BASIC".
Change in v7:
		1. Adjust position alphabetically in Kconfig and Makefile.
		2. Add static for loongson2_pll_base.
		3. Move other file-scope variables in probe.
Change in v6:
		1. NO change, but other patch in this series of patches has
		   changes.
Change in v5:
		1. Replace loongson2 with Loongson-2 in commit info.
		2. Replace Loongson2 with Loongson-2 in binding and
		   Kconfig file.
		3. Replace soc with SoC.
Change in v4:
		1. Fixup clock-names that replace "xxx-clk" with "xxx".
Change in v3:
		1. NO change, but other patch in this series of patches has
		   changes.
Change in v2:
		1. Update the include filename.
		2. Change string from refclk/REFCLK to ref/REF.

 MAINTAINERS                 |   1 +
 arch/loongarch/Kconfig      |   1 +
 drivers/clk/Kconfig         |   9 ++
 drivers/clk/Makefile        |   1 +
 drivers/clk/clk-loongson2.c | 286 ++++++++++++++++++++++++++++++++++++
 5 files changed, 298 insertions(+)
 create mode 100644 drivers/clk/clk-loongson2.c

diff --git a/MAINTAINERS b/MAINTAINERS
index ab94893fe2f6..73fa56f1fd5d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12025,6 +12025,7 @@ LOONGSON-2 SOC SERIES CLOCK DRIVER
 M:	Yinbo Zhu <zhuyinbo@loongson.cn>
 L:	linux-clk@vger.kernel.org
 S:	Maintained
+F:	drivers/clk/clk-loongson2.c
 F:	include/dt-bindings/clock/loongson,ls2k-clk.h
 
 LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
index 903096bd87f8..4f8f1b8f796d 100644
--- a/arch/loongarch/Kconfig
+++ b/arch/loongarch/Kconfig
@@ -127,6 +127,7 @@ config LOONGARCH
 	select USE_PERCPU_NUMA_NODE_ID
 	select USER_STACKTRACE_SUPPORT
 	select ZONE_DMA32
+	select COMMON_CLK
 
 config 32BIT
 	bool
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index d79905f3e174..d13626f63739 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -326,6 +326,15 @@ config COMMON_CLK_LOCHNAGAR
 	  This driver supports the clocking features of the Cirrus Logic
 	  Lochnagar audio development board.
 
+config COMMON_CLK_LOONGSON2
+	bool "Clock driver for Loongson-2 SoC"
+	depends on COMMON_CLK && OF
+	help
+	  This driver provides support for Clock Controller that base on
+	  Common Clock Framework Controller (CCF) on Loongson-2 SoC. The
+	  Clock Controller can generates and supplies clock to various
+	  peripherals within the SoC.
+
 config COMMON_CLK_NXP
 	def_bool COMMON_CLK && (ARCH_LPC18XX || ARCH_LPC32XX)
 	select REGMAP_MMIO if ARCH_LPC32XX
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index e3ca0d058a25..b298c5dabc1a 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_COMMON_CLK_K210)		+= clk-k210.o
 obj-$(CONFIG_LMK04832)			+= clk-lmk04832.o
 obj-$(CONFIG_COMMON_CLK_LAN966X)	+= clk-lan966x.o
 obj-$(CONFIG_COMMON_CLK_LOCHNAGAR)	+= clk-lochnagar.o
+obj-$(CONFIG_COMMON_CLK_LOONGSON2)	+= clk-loongson2.o
 obj-$(CONFIG_COMMON_CLK_MAX77686)	+= clk-max77686.o
 obj-$(CONFIG_COMMON_CLK_MAX9485)	+= clk-max9485.o
 obj-$(CONFIG_ARCH_MILBEAUT_M10V)	+= clk-milbeaut.o
diff --git a/drivers/clk/clk-loongson2.c b/drivers/clk/clk-loongson2.c
new file mode 100644
index 000000000000..7487effceeab
--- /dev/null
+++ b/drivers/clk/clk-loongson2.c
@@ -0,0 +1,286 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Author: Yinbo Zhu <zhuyinbo@loongson.cn>
+ * Copyright (C) 2022-2023 Loongson Technology Corporation Limited
+ */
+
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <dt-bindings/clock/loongson,ls2k-clk.h>
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+
+#define LOONGSON2_PLL_MULT_SHIFT		32
+#define LOONGSON2_PLL_MULT_WIDTH		10
+#define LOONGSON2_PLL_DIV_SHIFT			26
+#define LOONGSON2_PLL_DIV_WIDTH			6
+#define LOONGSON2_APB_FREQSCALE_SHIFT		20
+#define LOONGSON2_APB_FREQSCALE_WIDTH		3
+#define LOONGSON2_USB_FREQSCALE_SHIFT		16
+#define LOONGSON2_USB_FREQSCALE_WIDTH		3
+#define LOONGSON2_SATA_FREQSCALE_SHIFT		12
+#define LOONGSON2_SATA_FREQSCALE_WIDTH		3
+
+static void __iomem *loongson2_pll_base;
+
+static struct clk_hw *loongson2_clk_register(struct device *dev,
+					  const char *name,
+					  const char *parent_name,
+					  const struct clk_ops *ops,
+					  unsigned long flags)
+{
+	int ret;
+	struct clk_hw *hw;
+	struct clk_init_data init;
+
+	/* allocate the divider */
+	hw = kzalloc(sizeof(*hw), GFP_KERNEL);
+	if (!hw)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = ops;
+	init.flags = flags;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+	hw->init = &init;
+
+	/* register the clock */
+	ret = clk_hw_register(dev, hw);
+	if (ret) {
+		kfree(hw);
+		hw = ERR_PTR(ret);
+	}
+
+	return hw;
+}
+
+static struct clk_hw *loongson2_clk_pll_register(const char *name,
+				const char *parent, void __iomem *reg)
+{
+	u64 val;
+	u32 mult = 1, div = 1;
+
+	val = readq((void *)reg);
+
+	mult = (val >> LOONGSON2_PLL_MULT_SHIFT) &
+			clk_div_mask(LOONGSON2_PLL_MULT_WIDTH);
+	div = (val >> LOONGSON2_PLL_DIV_SHIFT) &
+			clk_div_mask(LOONGSON2_PLL_DIV_WIDTH);
+
+	return clk_hw_register_fixed_factor(NULL, name, parent,
+				CLK_SET_RATE_PARENT, mult, div);
+}
+
+static unsigned long loongson2_apb_recalc_rate(struct clk_hw *hw,
+					  unsigned long parent_rate)
+{
+	u64 val;
+	u32 mult;
+	unsigned long rate;
+
+	val = readq((void *)(loongson2_pll_base + 0x50));
+
+	mult = (val >> LOONGSON2_APB_FREQSCALE_SHIFT) &
+			clk_div_mask(LOONGSON2_APB_FREQSCALE_WIDTH);
+
+	rate = parent_rate * (mult + 1);
+	do_div(rate, 8);
+
+	return rate;
+}
+
+static const struct clk_ops loongson2_apb_clk_ops = {
+	.recalc_rate = loongson2_apb_recalc_rate,
+};
+
+static unsigned long loongson2_usb_recalc_rate(struct clk_hw *hw,
+					  unsigned long parent_rate)
+{
+	u64 val;
+	u32 mult;
+	unsigned long rate;
+
+	val = readq((void *)(loongson2_pll_base + 0x50));
+
+	mult = (val >> LOONGSON2_USB_FREQSCALE_SHIFT) &
+			clk_div_mask(LOONGSON2_USB_FREQSCALE_WIDTH);
+
+	rate = parent_rate * (mult + 1);
+	do_div(rate, 8);
+
+	return rate;
+}
+
+static const struct clk_ops loongson2_usb_clk_ops = {
+	.recalc_rate = loongson2_usb_recalc_rate,
+};
+
+static unsigned long loongson2_sata_recalc_rate(struct clk_hw *hw,
+					  unsigned long parent_rate)
+{
+	u64 val;
+	u32 mult;
+	unsigned long rate;
+
+	val = readq((void *)(loongson2_pll_base + 0x50));
+
+	mult = (val >> LOONGSON2_SATA_FREQSCALE_SHIFT) &
+			clk_div_mask(LOONGSON2_SATA_FREQSCALE_WIDTH);
+
+	rate = parent_rate * (mult + 1);
+	do_div(rate, 8);
+
+	return rate;
+}
+
+static const struct clk_ops loongson2_sata_clk_ops = {
+	.recalc_rate = loongson2_sata_recalc_rate,
+};
+
+static void loongson2_check_clk_hws(struct clk_hw *clks[], unsigned int count)
+{
+	unsigned int i;
+
+	for (i = 0; i < count; i++)
+		if (IS_ERR(clks[i]))
+			pr_err("Loongson2 clk %u: register failed with %ld\n"
+				, i, PTR_ERR(clks[i]));
+}
+
+static struct clk_hw *loongson2_obtain_fixed_clk_hw(
+					struct device_node *np,
+					const char *name)
+{
+	struct clk *clk;
+
+	clk = of_clk_get_by_name(np, name);
+	if (IS_ERR(clk))
+		return ERR_PTR(-ENOENT);
+
+	return __clk_get_hw(clk);
+}
+
+static void __init loongson2_clocks_init(struct device_node *np)
+{
+	struct clk_hw **hws;
+	struct clk_hw_onecell_data *clk_hw_data;
+	spinlock_t loongson2_clk_lock;
+
+	loongson2_pll_base = of_iomap(np, 0);
+
+	if (!loongson2_pll_base) {
+		pr_err("clk: unable to map loongson2 clk registers\n");
+		goto err;
+	}
+
+	clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, LOONGSON2_CLK_END),
+					GFP_KERNEL);
+	if (WARN_ON(!clk_hw_data))
+		goto err;
+
+	clk_hw_data->num = LOONGSON2_CLK_END;
+	hws = clk_hw_data->hws;
+
+	hws[LOONGSON2_REF_100M] = loongson2_obtain_fixed_clk_hw(np,
+						"ref_100m");
+
+	hws[LOONGSON2_NODE_PLL] = loongson2_clk_pll_register("node_pll",
+						"ref_100m",
+						loongson2_pll_base);
+
+	hws[LOONGSON2_DDR_PLL] = loongson2_clk_pll_register("ddr_pll",
+						"ref_100m",
+						loongson2_pll_base + 0x10);
+
+	hws[LOONGSON2_DC_PLL] = loongson2_clk_pll_register("dc_pll",
+						"ref_100m",
+						loongson2_pll_base + 0x20);
+
+	hws[LOONGSON2_PIX0_PLL] = loongson2_clk_pll_register("pix0_pll",
+						"ref_100m",
+						loongson2_pll_base + 0x30);
+
+	hws[LOONGSON2_PIX1_PLL] = loongson2_clk_pll_register("pix1_pll",
+						"ref_100m",
+						loongson2_pll_base + 0x40);
+
+	hws[LOONGSON2_NODE_CLK] = clk_hw_register_divider(NULL, "node",
+						"node_pll", 0,
+						loongson2_pll_base + 0x8, 0,
+						6, CLK_DIVIDER_ONE_BASED,
+						&loongson2_clk_lock);
+
+	/*
+	 * The hda clk divisor in the upper 32bits and the clk-prodiver
+	 * layer code doesn't support 64bit io operation thus a conversion
+	 * is required that subtract shift by 32 and add 4byte to the hda
+	 * address
+	 */
+	hws[LOONGSON2_HDA_CLK] = clk_hw_register_divider(NULL, "hda",
+						"ddr_pll", 0,
+						loongson2_pll_base + 0x22, 12,
+						7, CLK_DIVIDER_ONE_BASED,
+						&loongson2_clk_lock);
+
+	hws[LOONGSON2_GPU_CLK] = clk_hw_register_divider(NULL, "gpu",
+						"ddr_pll", 0,
+						loongson2_pll_base + 0x18, 22,
+						6, CLK_DIVIDER_ONE_BASED,
+						&loongson2_clk_lock);
+
+	hws[LOONGSON2_DDR_CLK] = clk_hw_register_divider(NULL, "ddr",
+						"ddr_pll", 0,
+						loongson2_pll_base + 0x18, 0,
+						6, CLK_DIVIDER_ONE_BASED,
+						&loongson2_clk_lock);
+
+	hws[LOONGSON2_GMAC_CLK] = clk_hw_register_divider(NULL, "gmac",
+						"dc_pll", 0,
+						loongson2_pll_base + 0x28, 22,
+						6, CLK_DIVIDER_ONE_BASED,
+						&loongson2_clk_lock);
+
+	hws[LOONGSON2_DC_CLK] = clk_hw_register_divider(NULL, "dc",
+						"dc_pll", 0,
+						loongson2_pll_base + 0x28, 0,
+						6, CLK_DIVIDER_ONE_BASED,
+						&loongson2_clk_lock);
+
+	hws[LOONGSON2_APB_CLK] = loongson2_clk_register(NULL, "apb",
+						"gmac",
+						&loongson2_apb_clk_ops, 0);
+
+	hws[LOONGSON2_USB_CLK] = loongson2_clk_register(NULL, "usb",
+						"gmac",
+						&loongson2_usb_clk_ops, 0);
+
+	hws[LOONGSON2_SATA_CLK] = loongson2_clk_register(NULL, "sata",
+						"gmac",
+						&loongson2_sata_clk_ops, 0);
+
+	hws[LOONGSON2_PIX0_CLK] = clk_hw_register_divider(NULL, "pix0",
+						"pix0_pll", 0,
+						loongson2_pll_base + 0x38, 0, 6,
+						CLK_DIVIDER_ONE_BASED,
+						&loongson2_clk_lock);
+
+	hws[LOONGSON2_PIX1_CLK] = clk_hw_register_divider(NULL, "pix1",
+						"pix1_pll", 0,
+						loongson2_pll_base + 0x48, 0, 6,
+						CLK_DIVIDER_ONE_BASED,
+						&loongson2_clk_lock);
+
+	loongson2_check_clk_hws(hws, LOONGSON2_CLK_END);
+
+	of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
+
+err:
+	iounmap(loongson2_pll_base);
+}
+
+CLK_OF_DECLARE(loongson2_clk, "loongson,ls2k-clk", loongson2_clocks_init);
-- 
2.31.1


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

* [PATCH v10 3/4] LoongArch: time: add of_clk_init in time_init
  2022-11-29  3:41 [PATCH v10 1/4] dt-bindings: clock: add loongson-2 clock include file Yinbo Zhu
  2022-11-29  3:41 ` [PATCH v10 2/4] clk: clk-loongson2: add clock controller driver support Yinbo Zhu
@ 2022-11-29  3:41 ` Yinbo Zhu
  2023-02-10 23:33   ` Stephen Boyd
  2022-11-29  3:41 ` [PATCH v10 4/4] dt-bindings: clock: add loongson-2 clock Yinbo Zhu
  2023-02-10 23:42 ` [PATCH v10 1/4] dt-bindings: clock: add loongson-2 clock include file Stephen Boyd
  3 siblings, 1 reply; 24+ messages in thread
From: Yinbo Zhu @ 2022-11-29  3:41 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rob Herring,
	Krzysztof Kozlowski, Huacai Chen, WANG Xuerui, Jiaxun Yang,
	Jianmin Lv, Yang Li, linux-clk, devicetree, linux-kernel,
	loongarch, Yinbo Zhu

The Loongson-2 clock controller driver used CLK_OF_DECLARE to
register clock subsystem that ask of_clk_init was called in
time_init and this patch was to addd such support.

Signed-off-by: Yinbo Zhu <zhuyinbo@loongson.cn>
---
 arch/loongarch/kernel/time.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/loongarch/kernel/time.c b/arch/loongarch/kernel/time.c
index 786735dcc8d6..09f20bc81798 100644
--- a/arch/loongarch/kernel/time.c
+++ b/arch/loongarch/kernel/time.c
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/sched_clock.h>
 #include <linux/spinlock.h>
+#include <linux/of_clk.h>
 
 #include <asm/cpu-features.h>
 #include <asm/loongarch.h>
@@ -214,6 +215,8 @@ int __init constant_clocksource_init(void)
 
 void __init time_init(void)
 {
+	of_clk_init(NULL);
+
 	if (!cpu_has_cpucfg)
 		const_clock_freq = cpu_clock_freq;
 	else
-- 
2.31.1


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

* [PATCH v10 4/4] dt-bindings: clock: add loongson-2 clock
  2022-11-29  3:41 [PATCH v10 1/4] dt-bindings: clock: add loongson-2 clock include file Yinbo Zhu
  2022-11-29  3:41 ` [PATCH v10 2/4] clk: clk-loongson2: add clock controller driver support Yinbo Zhu
  2022-11-29  3:41 ` [PATCH v10 3/4] LoongArch: time: add of_clk_init in time_init Yinbo Zhu
@ 2022-11-29  3:41 ` Yinbo Zhu
  2023-02-10 23:43   ` Stephen Boyd
  2023-02-10 23:42 ` [PATCH v10 1/4] dt-bindings: clock: add loongson-2 clock include file Stephen Boyd
  3 siblings, 1 reply; 24+ messages in thread
From: Yinbo Zhu @ 2022-11-29  3:41 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rob Herring,
	Krzysztof Kozlowski, Huacai Chen, WANG Xuerui, Jiaxun Yang,
	Jianmin Lv, Yang Li, linux-clk, devicetree, linux-kernel,
	loongarch, Yinbo Zhu
  Cc: Krzysztof Kozlowski

Add the Loongson-2 clock binding with DT schema format using
json-schema.

Signed-off-by: Yinbo Zhu <zhuyinbo@loongson.cn>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
Change in v10:
		1. NO change, but other patch in this series of patches has
		   changes.
Change in v9:
		1. Add all history changlog information.
Change in v8:
		1. NO change, but other patch in this series of patches has
		   changes.
Change in v7:
		1. NO change, but other patch in this series of patches has
		   changes.
Change in v6:
		1. NO change, but other patch in this series of patches has
		   changes.
Change in v5:
		1. NO change, but other patch in this series of patches has
		   changes.
Change in v4:
		1. NO change, but other patch in this series of patches has
		   changes.
Change in v3:
		1. Drop redundant (last) binding from the title.
		2. Drop "- |" between ref_100m node and clk node.
Change in v2:
		1. Drop "Binding" string in the title.
		2. Drop entire allOf and move the contents to top level.
		3. Change string "refclk_100m" to "ref_100m". 

 .../bindings/clock/loongson,ls2k-clk.yaml     | 63 +++++++++++++++++++
 MAINTAINERS                                   |  1 +
 2 files changed, 64 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml

diff --git a/Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml b/Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml
new file mode 100644
index 000000000000..63a59015987e
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml
@@ -0,0 +1,63 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/loongson,ls2k-clk.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Loongson-2 SoC Clock Control Module
+
+maintainers:
+  - Yinbo Zhu <zhuyinbo@loongson.cn>
+
+description: |
+  Loongson-2 SoC clock control module is an integrated clock controller, which
+  generates and supplies to all modules.
+
+properties:
+  compatible:
+    enum:
+      - loongson,ls2k-clk
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: 100m ref
+
+  clock-names:
+    items:
+      - const: ref_100m
+
+  '#clock-cells':
+    const: 1
+    description:
+      The clock consumer should specify the desired clock by having the clock
+      ID in its "clocks" phandle cell. See include/dt-bindings/clock/loongson,ls2k-clk.h
+      for the full list of Loongson-2 SoC clock IDs.
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - '#clock-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    ref_100m: clock-ref-100m {
+        compatible = "fixed-clock";
+        #clock-cells = <0>;
+        clock-frequency = <100000000>;
+        clock-output-names = "ref_100m";
+    };
+
+    clk: clock-controller@1fe00480 {
+        compatible = "loongson,ls2k-clk";
+        reg = <0x1fe00480 0x58>;
+        #clock-cells = <1>;
+        clocks = <&ref_100m>;
+        clock-names = "ref_100m";
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index 73fa56f1fd5d..0cdd1437c093 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12025,6 +12025,7 @@ LOONGSON-2 SOC SERIES CLOCK DRIVER
 M:	Yinbo Zhu <zhuyinbo@loongson.cn>
 L:	linux-clk@vger.kernel.org
 S:	Maintained
+F:	Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml
 F:	drivers/clk/clk-loongson2.c
 F:	include/dt-bindings/clock/loongson,ls2k-clk.h
 
-- 
2.31.1


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

* Re: [PATCH v10 2/4] clk: clk-loongson2: add clock controller driver support
  2022-11-29  3:41 ` [PATCH v10 2/4] clk: clk-loongson2: add clock controller driver support Yinbo Zhu
@ 2022-11-30  3:32   ` XiaochuanMao
       [not found]   ` <dfc61f0b-0051-4146-f534-6436e3076b65@loongson.cn>
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 24+ messages in thread
From: XiaochuanMao @ 2022-11-30  3:32 UTC (permalink / raw)
  To: Yinbo Zhu, Michael Turquette, Stephen Boyd, Rob Herring,
	Krzysztof Kozlowski, Huacai Chen, WANG Xuerui, Jiaxun Yang,
	Jianmin Lv, Yang Li, linux-clk, devicetree, linux-kernel,
	loongarch

hi, yinbo

On 2022/11/29 11:41, Yinbo Zhu wrote:
> This driver provides support for clock controller on Loongson-2 SoC,
> the Loongson-2 SoC uses a 100MHz clock as the PLL reference clock,
> there are five independent PLLs inside, each of which PLL can
> provide up to three sets of frequency dependent clock outputs.
>
> Signed-off-by: Yinbo Zhu <zhuyinbo@loongson.cn>
> ---
> Change in v10:
> 		1. Detach of_clk_init to another patch.
> Change in v9:
> 		1. Add all history changelog information.
> Change in v8:
> 		1. Remove the flag "CLK_IS_BASIC".
> Change in v7:
> 		1. Adjust position alphabetically in Kconfig and Makefile.
> 		2. Add static for loongson2_pll_base.
> 		3. Move other file-scope variables in probe.
> Change in v6:
> 		1. NO change, but other patch in this series of patches has
> 		   changes.
> Change in v5:
> 		1. Replace loongson2 with Loongson-2 in commit info.
> 		2. Replace Loongson2 with Loongson-2 in binding and
> 		   Kconfig file.
> 		3. Replace soc with SoC.
> Change in v4:
> 		1. Fixup clock-names that replace "xxx-clk" with "xxx".
> Change in v3:
> 		1. NO change, but other patch in this series of patches has
> 		   changes.
> Change in v2:
> 		1. Update the include filename.
> 		2. Change string from refclk/REFCLK to ref/REF.
>
>   MAINTAINERS                 |   1 +
>   arch/loongarch/Kconfig      |   1 +
>   drivers/clk/Kconfig         |   9 ++
>   drivers/clk/Makefile        |   1 +
>   drivers/clk/clk-loongson2.c | 286 ++++++++++++++++++++++++++++++++++++
>   5 files changed, 298 insertions(+)
>   create mode 100644 drivers/clk/clk-loongson2.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index ab94893fe2f6..73fa56f1fd5d 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -12025,6 +12025,7 @@ LOONGSON-2 SOC SERIES CLOCK DRIVER
>   M:	Yinbo Zhu <zhuyinbo@loongson.cn>
>   L:	linux-clk@vger.kernel.org
>   S:	Maintained
> +F:	drivers/clk/clk-loongson2.c
>   F:	include/dt-bindings/clock/loongson,ls2k-clk.h
>   
>   LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
> diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
> index 903096bd87f8..4f8f1b8f796d 100644
> --- a/arch/loongarch/Kconfig
> +++ b/arch/loongarch/Kconfig
> @@ -127,6 +127,7 @@ config LOONGARCH
>   	select USE_PERCPU_NUMA_NODE_ID
>   	select USER_STACKTRACE_SUPPORT
>   	select ZONE_DMA32
> +	select COMMON_CLK
>   
>   config 32BIT
>   	bool
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index d79905f3e174..d13626f63739 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -326,6 +326,15 @@ config COMMON_CLK_LOCHNAGAR
>   	  This driver supports the clocking features of the Cirrus Logic
>   	  Lochnagar audio development board.
>   
> +config COMMON_CLK_LOONGSON2
> +	bool "Clock driver for Loongson-2 SoC"
> +	depends on COMMON_CLK && OF
> +	help
> +	  This driver provides support for Clock Controller that base on
> +	  Common Clock Framework Controller (CCF) on Loongson-2 SoC. The
> +	  Clock Controller can generates and supplies clock to various
> +	  peripherals within the SoC.
> +
>   config COMMON_CLK_NXP
>   	def_bool COMMON_CLK && (ARCH_LPC18XX || ARCH_LPC32XX)
>   	select REGMAP_MMIO if ARCH_LPC32XX
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index e3ca0d058a25..b298c5dabc1a 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -43,6 +43,7 @@ obj-$(CONFIG_COMMON_CLK_K210)		+= clk-k210.o
>   obj-$(CONFIG_LMK04832)			+= clk-lmk04832.o
>   obj-$(CONFIG_COMMON_CLK_LAN966X)	+= clk-lan966x.o
>   obj-$(CONFIG_COMMON_CLK_LOCHNAGAR)	+= clk-lochnagar.o
> +obj-$(CONFIG_COMMON_CLK_LOONGSON2)	+= clk-loongson2.o
>   obj-$(CONFIG_COMMON_CLK_MAX77686)	+= clk-max77686.o
>   obj-$(CONFIG_COMMON_CLK_MAX9485)	+= clk-max9485.o
>   obj-$(CONFIG_ARCH_MILBEAUT_M10V)	+= clk-milbeaut.o
> diff --git a/drivers/clk/clk-loongson2.c b/drivers/clk/clk-loongson2.c
> new file mode 100644
> index 000000000000..7487effceeab
> --- /dev/null
> +++ b/drivers/clk/clk-loongson2.c
> @@ -0,0 +1,286 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Author: Yinbo Zhu <zhuyinbo@loongson.cn>
> + * Copyright (C) 2022-2023 Loongson Technology Corporation Limited
> + */
> +
> +#include <linux/clkdev.h>
> +#include <linux/err.h>
> +#include <linux/init.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <dt-bindings/clock/loongson,ls2k-clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/slab.h>
> +#include <linux/clk.h>
> +
> +#define LOONGSON2_PLL_MULT_SHIFT		32
> +#define LOONGSON2_PLL_MULT_WIDTH		10
> +#define LOONGSON2_PLL_DIV_SHIFT			26
> +#define LOONGSON2_PLL_DIV_WIDTH			6
> +#define LOONGSON2_APB_FREQSCALE_SHIFT		20
> +#define LOONGSON2_APB_FREQSCALE_WIDTH		3
> +#define LOONGSON2_USB_FREQSCALE_SHIFT		16
> +#define LOONGSON2_USB_FREQSCALE_WIDTH		3
> +#define LOONGSON2_SATA_FREQSCALE_SHIFT		12
> +#define LOONGSON2_SATA_FREQSCALE_WIDTH		3
> +
> +static void __iomem *loongson2_pll_base;
> +
> +static struct clk_hw *loongson2_clk_register(struct device *dev,
> +					  const char *name,
> +					  const char *parent_name,
> +					  const struct clk_ops *ops,
> +					  unsigned long flags)
> +{
> +	int ret;
> +	struct clk_hw *hw;
> +	struct clk_init_data init;
> +
> +	/* allocate the divider */
> +	hw = kzalloc(sizeof(*hw), GFP_KERNEL);
> +	if (!hw)
> +		return ERR_PTR(-ENOMEM);
> +
> +	init.name = name;
> +	init.ops = ops;
> +	init.flags = flags;
> +	init.parent_names = (parent_name ? &parent_name : NULL);
> +	init.num_parents = (parent_name ? 1 : 0);
> +	hw->init = &init;
> +
> +	/* register the clock */
> +	ret = clk_hw_register(dev, hw);
> +	if (ret) {
> +		kfree(hw);
> +		hw = ERR_PTR(ret);
> +	}
> +
> +	return hw;
> +}
> +
> +static struct clk_hw *loongson2_clk_pll_register(const char *name,
> +				const char *parent, void __iomem *reg)
> +{
> +	u64 val;
> +	u32 mult = 1, div = 1;
> +
> +	val = readq((void *)reg);
> +
> +	mult = (val >> LOONGSON2_PLL_MULT_SHIFT) &
> +			clk_div_mask(LOONGSON2_PLL_MULT_WIDTH);
> +	div = (val >> LOONGSON2_PLL_DIV_SHIFT) &
> +			clk_div_mask(LOONGSON2_PLL_DIV_WIDTH);
> +
> +	return clk_hw_register_fixed_factor(NULL, name, parent,
> +				CLK_SET_RATE_PARENT, mult, div);
> +}
> +
> +static unsigned long loongson2_apb_recalc_rate(struct clk_hw *hw,
> +					  unsigned long parent_rate)
> +{
> +	u64 val;
> +	u32 mult;
> +	unsigned long rate;
> +
> +	val = readq((void *)(loongson2_pll_base + 0x50));
> +
> +	mult = (val >> LOONGSON2_APB_FREQSCALE_SHIFT) &
> +			clk_div_mask(LOONGSON2_APB_FREQSCALE_WIDTH);
> +
> +	rate = parent_rate * (mult + 1);
> +	do_div(rate, 8);
> +
> +	return rate;
> +}
> +
> +static const struct clk_ops loongson2_apb_clk_ops = {
> +	.recalc_rate = loongson2_apb_recalc_rate,
> +};
> +
> +static unsigned long loongson2_usb_recalc_rate(struct clk_hw *hw,
> +					  unsigned long parent_rate)
> +{
> +	u64 val;
> +	u32 mult;
> +	unsigned long rate;
> +
> +	val = readq((void *)(loongson2_pll_base + 0x50));
> +
> +	mult = (val >> LOONGSON2_USB_FREQSCALE_SHIFT) &
> +			clk_div_mask(LOONGSON2_USB_FREQSCALE_WIDTH);
> +
> +	rate = parent_rate * (mult + 1);
> +	do_div(rate, 8);
> +
> +	return rate;
> +}
> +
> +static const struct clk_ops loongson2_usb_clk_ops = {
> +	.recalc_rate = loongson2_usb_recalc_rate,
> +};
> +
> +static unsigned long loongson2_sata_recalc_rate(struct clk_hw *hw,
> +					  unsigned long parent_rate)
> +{
> +	u64 val;
> +	u32 mult;
> +	unsigned long rate;
> +
> +	val = readq((void *)(loongson2_pll_base + 0x50));
it may be more common to use macro defintions instead of magic number. 
the clock configuration logic of  2k500 is  same as 2k1000, only the 
base  and offset are different。
> +
> +	mult = (val >> LOONGSON2_SATA_FREQSCALE_SHIFT) &
> +			clk_div_mask(LOONGSON2_SATA_FREQSCALE_WIDTH);
> +
> +	rate = parent_rate * (mult + 1);
> +	do_div(rate, 8);
> +
> +	return rate;
> +}
> +
> +static const struct clk_ops loongson2_sata_clk_ops = {
> +	.recalc_rate = loongson2_sata_recalc_rate,
> +};
> +
> +static void loongson2_check_clk_hws(struct clk_hw *clks[], unsigned int count)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < count; i++)
> +		if (IS_ERR(clks[i]))
> +			pr_err("Loongson2 clk %u: register failed with %ld\n"
> +				, i, PTR_ERR(clks[i]));
> +}
> +
> +static struct clk_hw *loongson2_obtain_fixed_clk_hw(
> +					struct device_node *np,
> +					const char *name)
> +{
> +	struct clk *clk;
> +
> +	clk = of_clk_get_by_name(np, name);
> +	if (IS_ERR(clk))
> +		return ERR_PTR(-ENOENT);
> +
> +	return __clk_get_hw(clk);
> +}
> +
> +static void __init loongson2_clocks_init(struct device_node *np)
> +{
> +	struct clk_hw **hws;
> +	struct clk_hw_onecell_data *clk_hw_data;
> +	spinlock_t loongson2_clk_lock;
> +
> +	loongson2_pll_base = of_iomap(np, 0);
> +
> +	if (!loongson2_pll_base) {
> +		pr_err("clk: unable to map loongson2 clk registers\n");
> +		goto err;
> +	}
> +
> +	clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, LOONGSON2_CLK_END),
> +					GFP_KERNEL);
> +	if (WARN_ON(!clk_hw_data))
> +		goto err;
> +
> +	clk_hw_data->num = LOONGSON2_CLK_END;
> +	hws = clk_hw_data->hws;
> +
> +	hws[LOONGSON2_REF_100M] = loongson2_obtain_fixed_clk_hw(np,
> +						"ref_100m");
> +
> +	hws[LOONGSON2_NODE_PLL] = loongson2_clk_pll_register("node_pll",
> +						"ref_100m",
> +						loongson2_pll_base);
> +
> +	hws[LOONGSON2_DDR_PLL] = loongson2_clk_pll_register("ddr_pll",
> +						"ref_100m",
> +						loongson2_pll_base + 0x10);
> +
> +	hws[LOONGSON2_DC_PLL] = loongson2_clk_pll_register("dc_pll",
> +						"ref_100m",
> +						loongson2_pll_base + 0x20);
> +
> +	hws[LOONGSON2_PIX0_PLL] = loongson2_clk_pll_register("pix0_pll",
> +						"ref_100m",
> +						loongson2_pll_base + 0x30);
> +
> +	hws[LOONGSON2_PIX1_PLL] = loongson2_clk_pll_register("pix1_pll",
> +						"ref_100m",
> +						loongson2_pll_base + 0x40);
> +
> +	hws[LOONGSON2_NODE_CLK] = clk_hw_register_divider(NULL, "node",
> +						"node_pll", 0,
> +						loongson2_pll_base + 0x8, 0,
> +						6, CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	/*
> +	 * The hda clk divisor in the upper 32bits and the clk-prodiver
> +	 * layer code doesn't support 64bit io operation thus a conversion
> +	 * is required that subtract shift by 32 and add 4byte to the hda
> +	 * address
> +	 */
> +	hws[LOONGSON2_HDA_CLK] = clk_hw_register_divider(NULL, "hda",
> +						"ddr_pll", 0,
> +						loongson2_pll_base + 0x22, 12,
> +						7, CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	hws[LOONGSON2_GPU_CLK] = clk_hw_register_divider(NULL, "gpu",
> +						"ddr_pll", 0,
> +						loongson2_pll_base + 0x18, 22,
> +						6, CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	hws[LOONGSON2_DDR_CLK] = clk_hw_register_divider(NULL, "ddr",
> +						"ddr_pll", 0,
> +						loongson2_pll_base + 0x18, 0,
> +						6, CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	hws[LOONGSON2_GMAC_CLK] = clk_hw_register_divider(NULL, "gmac",
> +						"dc_pll", 0,
> +						loongson2_pll_base + 0x28, 22,
> +						6, CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	hws[LOONGSON2_DC_CLK] = clk_hw_register_divider(NULL, "dc",
> +						"dc_pll", 0,
> +						loongson2_pll_base + 0x28, 0,
> +						6, CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	hws[LOONGSON2_APB_CLK] = loongson2_clk_register(NULL, "apb",
> +						"gmac",
> +						&loongson2_apb_clk_ops, 0);
> +
> +	hws[LOONGSON2_USB_CLK] = loongson2_clk_register(NULL, "usb",
> +						"gmac",
> +						&loongson2_usb_clk_ops, 0);
> +
> +	hws[LOONGSON2_SATA_CLK] = loongson2_clk_register(NULL, "sata",
> +						"gmac",
> +						&loongson2_sata_clk_ops, 0);
> +
> +	hws[LOONGSON2_PIX0_CLK] = clk_hw_register_divider(NULL, "pix0",
> +						"pix0_pll", 0,
> +						loongson2_pll_base + 0x38, 0, 6,
> +						CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	hws[LOONGSON2_PIX1_CLK] = clk_hw_register_divider(NULL, "pix1",
> +						"pix1_pll", 0,
> +						loongson2_pll_base + 0x48, 0, 6,
> +						CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
above this,   it may be more common to use macro defintions instead of 
magic number. the clock configuration logic of 2k500 is same as 2k1000, 
only the base  and offset are different
> +	loongson2_check_clk_hws(hws, LOONGSON2_CLK_END);
> +
> +	of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
> +
> +err:
> +	iounmap(loongson2_pll_base);
> +}
> +
> +CLK_OF_DECLARE(loongson2_clk, "loongson,ls2k-clk", loongson2_clocks_init);


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

* Re: [PATCH v10 2/4] clk: clk-loongson2: add clock controller driver support
       [not found]   ` <dfc61f0b-0051-4146-f534-6436e3076b65@loongson.cn>
@ 2022-11-30 10:16     ` Yinbo Zhu
  0 siblings, 0 replies; 24+ messages in thread
From: Yinbo Zhu @ 2022-11-30 10:16 UTC (permalink / raw)
  To: XiaochuanMao, Michael Turquette, Stephen Boyd, Rob Herring,
	Krzysztof Kozlowski, Huacai Chen, WANG Xuerui, Jiaxun Yang,
	Jianmin Lv, Yang Li, linux-clk, devicetree, linux-kernel,
	loongarch


在 2022/11/30 11:27, XiaochuanMao 写道:
>
> hi, yinbo
>
> On 2022/11/29 11:41, Yinbo Zhu wrote:
>> This driver provides support for clock controller on Loongson-2 SoC,
>> the Loongson-2 SoC uses a 100MHz clock as the PLL reference clock,
>> there are five independent PLLs inside, each of which PLL can
>> provide up to three sets of frequency dependent clock outputs.
>>
>> Signed-off-by: Yinbo Zhu<zhuyinbo@loongson.cn>
>> ---
>> Change in v10:
>> 		1. Detach of_clk_init to another patch.
>> Change in v9:
>> 		1. Add all history changelog information.
>> Change in v8:
>> 		1. Remove the flag "CLK_IS_BASIC".
>> Change in v7:
>> 		1. Adjust position alphabetically in Kconfig and Makefile.
>> 		2. Add static for loongson2_pll_base.
>> 		3. Move other file-scope variables in probe.
>> Change in v6:
>> 		1. NO change, but other patch in this series of patches has
>> 		   changes.
>> Change in v5:
>> 		1. Replace loongson2 with Loongson-2 in commit info.
>> 		2. Replace Loongson2 with Loongson-2 in binding and
>> 		   Kconfig file.
>> 		3. Replace soc with SoC.
>> Change in v4:
>> 		1. Fixup clock-names that replace "xxx-clk" with "xxx".
>> Change in v3:
>> 		1. NO change, but other patch in this series of patches has
>> 		   changes.
>> Change in v2:
>> 		1. Update the include filename.
>> 		2. Change string from refclk/REFCLK to ref/REF.
>>
>>   MAINTAINERS                 |   1 +
>>   arch/loongarch/Kconfig      |   1 +
>>   drivers/clk/Kconfig         |   9 ++
>>   drivers/clk/Makefile        |   1 +
>>   drivers/clk/clk-loongson2.c | 286 ++++++++++++++++++++++++++++++++++++
>>   5 files changed, 298 insertions(+)
>>   create mode 100644 drivers/clk/clk-loongson2.c
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index ab94893fe2f6..73fa56f1fd5d 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -12025,6 +12025,7 @@ LOONGSON-2 SOC SERIES CLOCK DRIVER
>>   M:	Yinbo Zhu<zhuyinbo@loongson.cn>
>>   L:	linux-clk@vger.kernel.org
>>   S:	Maintained
>> +F:	drivers/clk/clk-loongson2.c
>>   F:	include/dt-bindings/clock/loongson,ls2k-clk.h
>>   
>>   LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
>> diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
>> index 903096bd87f8..4f8f1b8f796d 100644
>> --- a/arch/loongarch/Kconfig
>> +++ b/arch/loongarch/Kconfig
>> @@ -127,6 +127,7 @@ config LOONGARCH
>>   	select USE_PERCPU_NUMA_NODE_ID
>>   	select USER_STACKTRACE_SUPPORT
>>   	select ZONE_DMA32
>> +	select COMMON_CLK
>>   
>>   config 32BIT
>>   	bool
>> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
>> index d79905f3e174..d13626f63739 100644
>> --- a/drivers/clk/Kconfig
>> +++ b/drivers/clk/Kconfig
>> @@ -326,6 +326,15 @@ config COMMON_CLK_LOCHNAGAR
>>   	  This driver supports the clocking features of the Cirrus Logic
>>   	  Lochnagar audio development board.
>>   
>> +config COMMON_CLK_LOONGSON2
>> +	bool "Clock driver for Loongson-2 SoC"
>> +	depends on COMMON_CLK && OF
>> +	help
>> +	  This driver provides support for Clock Controller that base on
>> +	  Common Clock Framework Controller (CCF) on Loongson-2 SoC. The
>> +	  Clock Controller can generates and supplies clock to various
>> +	  peripherals within the SoC.
>> +
>>   config COMMON_CLK_NXP
>>   	def_bool COMMON_CLK && (ARCH_LPC18XX || ARCH_LPC32XX)
>>   	select REGMAP_MMIO if ARCH_LPC32XX
>> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>> index e3ca0d058a25..b298c5dabc1a 100644
>> --- a/drivers/clk/Makefile
>> +++ b/drivers/clk/Makefile
>> @@ -43,6 +43,7 @@ obj-$(CONFIG_COMMON_CLK_K210)		+= clk-k210.o
>>   obj-$(CONFIG_LMK04832)			+= clk-lmk04832.o
>>   obj-$(CONFIG_COMMON_CLK_LAN966X)	+= clk-lan966x.o
>>   obj-$(CONFIG_COMMON_CLK_LOCHNAGAR)	+= clk-lochnagar.o
>> +obj-$(CONFIG_COMMON_CLK_LOONGSON2)	+= clk-loongson2.o
>>   obj-$(CONFIG_COMMON_CLK_MAX77686)	+= clk-max77686.o
>>   obj-$(CONFIG_COMMON_CLK_MAX9485)	+= clk-max9485.o
>>   obj-$(CONFIG_ARCH_MILBEAUT_M10V)	+= clk-milbeaut.o
>> diff --git a/drivers/clk/clk-loongson2.c b/drivers/clk/clk-loongson2.c
>> new file mode 100644
>> index 000000000000..7487effceeab
>> --- /dev/null
>> +++ b/drivers/clk/clk-loongson2.c
>> @@ -0,0 +1,286 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * Author: Yinbo Zhu<zhuyinbo@loongson.cn>
>> + * Copyright (C) 2022-2023 Loongson Technology Corporation Limited
>> + */
>> +
>> +#include <linux/clkdev.h>
>> +#include <linux/err.h>
>> +#include <linux/init.h>
>> +#include <linux/of.h>
>> +#include <linux/of_address.h>
>> +#include <dt-bindings/clock/loongson,ls2k-clk.h>
>> +#include <linux/clk-provider.h>
>> +#include <linux/slab.h>
>> +#include <linux/clk.h>
>> +
>> +#define LOONGSON2_PLL_MULT_SHIFT		32
>> +#define LOONGSON2_PLL_MULT_WIDTH		10
>> +#define LOONGSON2_PLL_DIV_SHIFT			26
>> +#define LOONGSON2_PLL_DIV_WIDTH			6
>> +#define LOONGSON2_APB_FREQSCALE_SHIFT		20
>> +#define LOONGSON2_APB_FREQSCALE_WIDTH		3
>> +#define LOONGSON2_USB_FREQSCALE_SHIFT		16
>> +#define LOONGSON2_USB_FREQSCALE_WIDTH		3
>> +#define LOONGSON2_SATA_FREQSCALE_SHIFT		12
>> +#define LOONGSON2_SATA_FREQSCALE_WIDTH		3
>> +
>> +static void __iomem *loongson2_pll_base;
>> +
>> +static struct clk_hw *loongson2_clk_register(struct device *dev,
>> +					  const char *name,
>> +					  const char *parent_name,
>> +					  const struct clk_ops *ops,
>> +					  unsigned long flags)
>> +{
>> +	int ret;
>> +	struct clk_hw *hw;
>> +	struct clk_init_data init;
>> +
>> +	/* allocate the divider */
>> +	hw = kzalloc(sizeof(*hw), GFP_KERNEL);
>> +	if (!hw)
>> +		return ERR_PTR(-ENOMEM);
>> +
>> +	init.name = name;
>> +	init.ops = ops;
>> +	init.flags = flags;
>> +	init.parent_names = (parent_name ? &parent_name : NULL);
>> +	init.num_parents = (parent_name ? 1 : 0);
>> +	hw->init = &init;
>> +
>> +	/* register the clock */
>> +	ret = clk_hw_register(dev, hw);
>> +	if (ret) {
>> +		kfree(hw);
>> +		hw = ERR_PTR(ret);
>> +	}
>> +
>> +	return hw;
>> +}
>> +
>> +static struct clk_hw *loongson2_clk_pll_register(const char *name,
>> +				const char *parent, void __iomem *reg)
>> +{
>> +	u64 val;
>> +	u32 mult = 1, div = 1;
>> +
>> +	val = readq((void *)reg);
>> +
>> +	mult = (val >> LOONGSON2_PLL_MULT_SHIFT) &
>> +			clk_div_mask(LOONGSON2_PLL_MULT_WIDTH);
>> +	div = (val >> LOONGSON2_PLL_DIV_SHIFT) &
>> +			clk_div_mask(LOONGSON2_PLL_DIV_WIDTH);
>> +
>> +	return clk_hw_register_fixed_factor(NULL, name, parent,
>> +				CLK_SET_RATE_PARENT, mult, div);
>> +}
>> +
>> +static unsigned long loongson2_apb_recalc_rate(struct clk_hw *hw,
>> +					  unsigned long parent_rate)
>> +{
>> +	u64 val;
>> +	u32 mult;
>> +	unsigned long rate;
>> +
>> +	val = readq((void *)(loongson2_pll_base + 0x50));
>> +
> it may be more common to use macro defintions instead of magic number. 
> the clock configuration logic of  2k500 is  same as 2k1000,  only the 
> base  and offset are different。
<https://fanyi.baidu.com/###>
In addition to address differences, there are others, but according to 
internal requirements,
2k1000 is considered first.  2k500 clock will be added later use other 
compatibility method in
this driver.
>> +	mult = (val >> LOONGSON2_APB_FREQSCALE_SHIFT) &
>> +			clk_div_mask(LOONGSON2_APB_FREQSCALE_WIDTH);
>> +
>> +	rate = parent_rate * (mult + 1);
>> +	do_div(rate, 8);
>> +
>> +	return rate;
>> +}
>> +
>> +static const struct clk_ops loongson2_apb_clk_ops = {
>> +	.recalc_rate = loongson2_apb_recalc_rate,
>> +};
>> +
>> +static unsigned long loongson2_usb_recalc_rate(struct clk_hw *hw,
>> +					  unsigned long parent_rate)
>> +{
>> +	u64 val;
>> +	u32 mult;
>> +	unsigned long rate;
>> +
>> +	val = readq((void *)(loongson2_pll_base + 0x50));
>> +
>> +	mult = (val >> LOONGSON2_USB_FREQSCALE_SHIFT) &
>> +			clk_div_mask(LOONGSON2_USB_FREQSCALE_WIDTH);
>> +
>> +	rate = parent_rate * (mult + 1);
>> +	do_div(rate, 8);
>> +
>> +	return rate;
>> +}
>> +
>> +static const struct clk_ops loongson2_usb_clk_ops = {
>> +	.recalc_rate = loongson2_usb_recalc_rate,
>> +};
>> +
>> +static unsigned long loongson2_sata_recalc_rate(struct clk_hw *hw,
>> +					  unsigned long parent_rate)
>> +{
>> +	u64 val;
>> +	u32 mult;
>> +	unsigned long rate;
>> +
>> +	val = readq((void *)(loongson2_pll_base + 0x50));
>> +
>> +	mult = (val >> LOONGSON2_SATA_FREQSCALE_SHIFT) &
>> +			clk_div_mask(LOONGSON2_SATA_FREQSCALE_WIDTH);
>> +
>> +	rate = parent_rate * (mult + 1);
>> +	do_div(rate, 8);
>> +
>> +	return rate;
>> +}
>> +
>> +static const struct clk_ops loongson2_sata_clk_ops = {
>> +	.recalc_rate = loongson2_sata_recalc_rate,
>> +};
>> +
>> +static void loongson2_check_clk_hws(struct clk_hw *clks[], unsigned int count)
>> +{
>> +	unsigned int i;
>> +
>> +	for (i = 0; i < count; i++)
>> +		if (IS_ERR(clks[i]))
>> +			pr_err("Loongson2 clk %u: register failed with %ld\n"
>> +				, i, PTR_ERR(clks[i]));
>> +}
>> +
>> +static struct clk_hw *loongson2_obtain_fixed_clk_hw(
>> +					struct device_node *np,
>> +					const char *name)
>> +{
>> +	struct clk *clk;
>> +
>> +	clk = of_clk_get_by_name(np, name);
>> +	if (IS_ERR(clk))
>> +		return ERR_PTR(-ENOENT);
>> +
>> +	return __clk_get_hw(clk);
>> +}
>> +
>> +static void __init loongson2_clocks_init(struct device_node *np)
>> +{
>> +	struct clk_hw **hws;
>> +	struct clk_hw_onecell_data *clk_hw_data;
>> +	spinlock_t loongson2_clk_lock;
>> +
>> +	loongson2_pll_base = of_iomap(np, 0);
>> +
>> +	if (!loongson2_pll_base) {
>> +		pr_err("clk: unable to map loongson2 clk registers\n");
>> +		goto err;
>> +	}
>> +
>> +	clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, LOONGSON2_CLK_END),
>> +					GFP_KERNEL);
>> +	if (WARN_ON(!clk_hw_data))
>> +		goto err;
>> +
>> +	clk_hw_data->num = LOONGSON2_CLK_END;
>> +	hws = clk_hw_data->hws;
>> +
>> +	hws[LOONGSON2_REF_100M] = loongson2_obtain_fixed_clk_hw(np,
>> +						"ref_100m");
>> +
>> +	hws[LOONGSON2_NODE_PLL] = loongson2_clk_pll_register("node_pll",
>> +						"ref_100m",
>> +						loongson2_pll_base);
>> +
>> +	hws[LOONGSON2_DDR_PLL] = loongson2_clk_pll_register("ddr_pll",
>> +						"ref_100m",
>> +						loongson2_pll_base + 0x10);
>> +
>> +	hws[LOONGSON2_DC_PLL] = loongson2_clk_pll_register("dc_pll",
>> +						"ref_100m",
>> +						loongson2_pll_base + 0x20);
>> +
>> +	hws[LOONGSON2_PIX0_PLL] = loongson2_clk_pll_register("pix0_pll",
>> +						"ref_100m",
>> +						loongson2_pll_base + 0x30);
>> +
>> +	hws[LOONGSON2_PIX1_PLL] = loongson2_clk_pll_register("pix1_pll",
>> +						"ref_100m",
>> +						loongson2_pll_base + 0x40);
>> +
>> +	hws[LOONGSON2_NODE_CLK] = clk_hw_register_divider(NULL, "node",
>> +						"node_pll", 0,
>> +						loongson2_pll_base + 0x8, 0,
>> +						6, CLK_DIVIDER_ONE_BASED,
>> +						&loongson2_clk_lock);
>> +
>> +	/*
>> +	 * The hda clk divisor in the upper 32bits and the clk-prodiver
>> +	 * layer code doesn't support 64bit io operation thus a conversion
>> +	 * is required that subtract shift by 32 and add 4byte to the hda
>> +	 * address
>> +	 */
>> +	hws[LOONGSON2_HDA_CLK] = clk_hw_register_divider(NULL, "hda",
>> +						"ddr_pll", 0,
>> +						loongson2_pll_base + 0x22, 12,
>> +						7, CLK_DIVIDER_ONE_BASED,
>> +						&loongson2_clk_lock);
>> +
>> +	hws[LOONGSON2_GPU_CLK] = clk_hw_register_divider(NULL, "gpu",
>> +						"ddr_pll", 0,
>> +						loongson2_pll_base + 0x18, 22,
>> +						6, CLK_DIVIDER_ONE_BASED,
>> +						&loongson2_clk_lock);
>> +
>> +	hws[LOONGSON2_DDR_CLK] = clk_hw_register_divider(NULL, "ddr",
>> +						"ddr_pll", 0,
>> +						loongson2_pll_base + 0x18, 0,
>> +						6, CLK_DIVIDER_ONE_BASED,
>> +						&loongson2_clk_lock);
>> +
>> +	hws[LOONGSON2_GMAC_CLK] = clk_hw_register_divider(NULL, "gmac",
>> +						"dc_pll", 0,
>> +						loongson2_pll_base + 0x28, 22,
>> +						6, CLK_DIVIDER_ONE_BASED,
>> +						&loongson2_clk_lock);
>> +
>> +	hws[LOONGSON2_DC_CLK] = clk_hw_register_divider(NULL, "dc",
>> +						"dc_pll", 0,
>> +						loongson2_pll_base + 0x28, 0,
>> +						6, CLK_DIVIDER_ONE_BASED,
>> +						&loongson2_clk_lock);
>> +
>> +	hws[LOONGSON2_APB_CLK] = loongson2_clk_register(NULL, "apb",
>> +						"gmac",
>> +						&loongson2_apb_clk_ops, 0);
>> +
>> +	hws[LOONGSON2_USB_CLK] = loongson2_clk_register(NULL, "usb",
>> +						"gmac",
>> +						&loongson2_usb_clk_ops, 0);
>> +
>> +	hws[LOONGSON2_SATA_CLK] = loongson2_clk_register(NULL, "sata",
>> +						"gmac",
>> +						&loongson2_sata_clk_ops, 0);
>> +
>> +	hws[LOONGSON2_PIX0_CLK] = clk_hw_register_divider(NULL, "pix0",
>> +						"pix0_pll", 0,
>> +						loongson2_pll_base + 0x38, 0, 6,
>> +						CLK_DIVIDER_ONE_BASED,
>> +						&loongson2_clk_lock);
>> +
>> +	hws[LOONGSON2_PIX1_CLK] = clk_hw_register_divider(NULL, "pix1",
>> +						"pix1_pll", 0,
>> +						loongson2_pll_base + 0x48, 0, 6,
>> +						CLK_DIVIDER_ONE_BASED,
>> +						&loongson2_clk_lock);
> above this,   it may be more common to use macro defintions instead of 
> magic number. the clock configuration logic of 2k500 is same as 
> 2k1000, only the base  and offset are different。 

clk_hw_register_divider is a commone interface, I think

>> +
>> +	loongson2_check_clk_hws(hws, LOONGSON2_CLK_END);
>> +
>> +	of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
>> +
>> +err:
>> +	iounmap(loongson2_pll_base);
>> +}
>> +
>> +CLK_OF_DECLARE(loongson2_clk, "loongson,ls2k-clk", loongson2_clocks_init);
>
>
> thanks
>


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

* Re: [PATCH v10 2/4] clk: clk-loongson2: add clock controller driver support
  2022-11-29  3:41 ` [PATCH v10 2/4] clk: clk-loongson2: add clock controller driver support Yinbo Zhu
  2022-11-30  3:32   ` XiaochuanMao
       [not found]   ` <dfc61f0b-0051-4146-f534-6436e3076b65@loongson.cn>
@ 2022-11-30 13:14   ` XiaochuanMao
  2022-11-30 22:49     ` Yinbo Zhu
  2022-12-07  2:15   ` Yinbo Zhu
                     ` (2 subsequent siblings)
  5 siblings, 1 reply; 24+ messages in thread
From: XiaochuanMao @ 2022-11-30 13:14 UTC (permalink / raw)
  To: Yinbo Zhu, Michael Turquette, Stephen Boyd, Rob Herring,
	Krzysztof Kozlowski, Huacai Chen, WANG Xuerui, Jiaxun Yang,
	Jianmin Lv, Yang Li, linux-clk, devicetree, linux-kernel,
	loongarch

hi yinbo

On 2022/11/29 11:41, Yinbo Zhu wrote:
> This driver provides support for clock controller on Loongson-2 SoC,
> the Loongson-2 SoC uses a 100MHz clock as the PLL reference clock,
> there are five independent PLLs inside, each of which PLL can
> provide up to three sets of frequency dependent clock outputs.
>
> Signed-off-by: Yinbo Zhu <zhuyinbo@loongson.cn>
> ---
> Change in v10:
> 		1. Detach of_clk_init to another patch.
> Change in v9:
> 		1. Add all history changelog information.
> Change in v8:
> 		1. Remove the flag "CLK_IS_BASIC".
> Change in v7:
> 		1. Adjust position alphabetically in Kconfig and Makefile.
> 		2. Add static for loongson2_pll_base.
> 		3. Move other file-scope variables in probe.
> Change in v6:
> 		1. NO change, but other patch in this series of patches has
> 		   changes.
> Change in v5:
> 		1. Replace loongson2 with Loongson-2 in commit info.
> 		2. Replace Loongson2 with Loongson-2 in binding and
> 		   Kconfig file.
> 		3. Replace soc with SoC.
> Change in v4:
> 		1. Fixup clock-names that replace "xxx-clk" with "xxx".
> Change in v3:
> 		1. NO change, but other patch in this series of patches has
> 		   changes.
> Change in v2:
> 		1. Update the include filename.
> 		2. Change string from refclk/REFCLK to ref/REF.
>
>   MAINTAINERS                 |   1 +
>   arch/loongarch/Kconfig      |   1 +
>   drivers/clk/Kconfig         |   9 ++
>   drivers/clk/Makefile        |   1 +
>   drivers/clk/clk-loongson2.c | 286 ++++++++++++++++++++++++++++++++++++
>   5 files changed, 298 insertions(+)
>   create mode 100644 drivers/clk/clk-loongson2.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index ab94893fe2f6..73fa56f1fd5d 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -12025,6 +12025,7 @@ LOONGSON-2 SOC SERIES CLOCK DRIVER
>   M:	Yinbo Zhu <zhuyinbo@loongson.cn>
>   L:	linux-clk@vger.kernel.org
>   S:	Maintained
> +F:	drivers/clk/clk-loongson2.c
>   F:	include/dt-bindings/clock/loongson,ls2k-clk.h
>   
>   LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
> diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
> index 903096bd87f8..4f8f1b8f796d 100644
> --- a/arch/loongarch/Kconfig
> +++ b/arch/loongarch/Kconfig
> @@ -127,6 +127,7 @@ config LOONGARCH
>   	select USE_PERCPU_NUMA_NODE_ID
>   	select USER_STACKTRACE_SUPPORT
>   	select ZONE_DMA32
> +	select COMMON_CLK
>   
>   config 32BIT
>   	bool
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index d79905f3e174..d13626f63739 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -326,6 +326,15 @@ config COMMON_CLK_LOCHNAGAR
>   	  This driver supports the clocking features of the Cirrus Logic
>   	  Lochnagar audio development board.
>   
> +config COMMON_CLK_LOONGSON2
> +	bool "Clock driver for Loongson-2 SoC"
> +	depends on COMMON_CLK && OF
> +	help
> +	  This driver provides support for Clock Controller that base on
> +	  Common Clock Framework Controller (CCF) on Loongson-2 SoC. The
> +	  Clock Controller can generates and supplies clock to various
> +	  peripherals within the SoC.
> +
>   config COMMON_CLK_NXP
>   	def_bool COMMON_CLK && (ARCH_LPC18XX || ARCH_LPC32XX)
>   	select REGMAP_MMIO if ARCH_LPC32XX
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index e3ca0d058a25..b298c5dabc1a 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -43,6 +43,7 @@ obj-$(CONFIG_COMMON_CLK_K210)		+= clk-k210.o
>   obj-$(CONFIG_LMK04832)			+= clk-lmk04832.o
>   obj-$(CONFIG_COMMON_CLK_LAN966X)	+= clk-lan966x.o
>   obj-$(CONFIG_COMMON_CLK_LOCHNAGAR)	+= clk-lochnagar.o
> +obj-$(CONFIG_COMMON_CLK_LOONGSON2)	+= clk-loongson2.o
>   obj-$(CONFIG_COMMON_CLK_MAX77686)	+= clk-max77686.o
>   obj-$(CONFIG_COMMON_CLK_MAX9485)	+= clk-max9485.o
>   obj-$(CONFIG_ARCH_MILBEAUT_M10V)	+= clk-milbeaut.o
> diff --git a/drivers/clk/clk-loongson2.c b/drivers/clk/clk-loongson2.c
> new file mode 100644
> index 000000000000..7487effceeab
> --- /dev/null
> +++ b/drivers/clk/clk-loongson2.c
> @@ -0,0 +1,286 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Author: Yinbo Zhu <zhuyinbo@loongson.cn>
> + * Copyright (C) 2022-2023 Loongson Technology Corporation Limited
> + */
> +
> +#include <linux/clkdev.h>
> +#include <linux/err.h>
> +#include <linux/init.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <dt-bindings/clock/loongson,ls2k-clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/slab.h>
> +#include <linux/clk.h>
> +
> +#define LOONGSON2_PLL_MULT_SHIFT		32
> +#define LOONGSON2_PLL_MULT_WIDTH		10
> +#define LOONGSON2_PLL_DIV_SHIFT			26
> +#define LOONGSON2_PLL_DIV_WIDTH			6
> +#define LOONGSON2_APB_FREQSCALE_SHIFT		20
> +#define LOONGSON2_APB_FREQSCALE_WIDTH		3
> +#define LOONGSON2_USB_FREQSCALE_SHIFT		16
> +#define LOONGSON2_USB_FREQSCALE_WIDTH		3
> +#define LOONGSON2_SATA_FREQSCALE_SHIFT		12
> +#define LOONGSON2_SATA_FREQSCALE_WIDTH		3
> +
> +static void __iomem *loongson2_pll_base;
> +
> +static struct clk_hw *loongson2_clk_register(struct device *dev,
> +					  const char *name,
> +					  const char *parent_name,
> +					  const struct clk_ops *ops,
> +					  unsigned long flags)
> +{
> +	int ret;
> +	struct clk_hw *hw;
> +	struct clk_init_data init;
> +
> +	/* allocate the divider */
> +	hw = kzalloc(sizeof(*hw), GFP_KERNEL);
> +	if (!hw)
> +		return ERR_PTR(-ENOMEM);
> +
> +	init.name = name;
> +	init.ops = ops;
> +	init.flags = flags;
> +	init.parent_names = (parent_name ? &parent_name : NULL);
> +	init.num_parents = (parent_name ? 1 : 0);
> +	hw->init = &init;
> +
> +	/* register the clock */
> +	ret = clk_hw_register(dev, hw);
> +	if (ret) {
> +		kfree(hw);
> +		hw = ERR_PTR(ret);
> +	}
> +
> +	return hw;
> +}
> +
> +static struct clk_hw *loongson2_clk_pll_register(const char *name,
> +				const char *parent, void __iomem *reg)
> +{
> +	u64 val;
> +	u32 mult = 1, div = 1;
> +
> +	val = readq((void *)reg);
> +
> +	mult = (val >> LOONGSON2_PLL_MULT_SHIFT) &
> +			clk_div_mask(LOONGSON2_PLL_MULT_WIDTH);
> +	div = (val >> LOONGSON2_PLL_DIV_SHIFT) &
> +			clk_div_mask(LOONGSON2_PLL_DIV_WIDTH);
> +
> +	return clk_hw_register_fixed_factor(NULL, name, parent,
> +				CLK_SET_RATE_PARENT, mult, div);
> +}
> +
> +static unsigned long loongson2_apb_recalc_rate(struct clk_hw *hw,
> +					  unsigned long parent_rate)
> +{
> +	u64 val;
> +	u32 mult;
> +	unsigned long rate;
> +
> +	val = readq((void *)(loongson2_pll_base + 0x50));
> +
> +	mult = (val >> LOONGSON2_APB_FREQSCALE_SHIFT) &
> +			clk_div_mask(LOONGSON2_APB_FREQSCALE_WIDTH);
> +
> +	rate = parent_rate * (mult + 1);
> +	do_div(rate, 8);
> +
> +	return rate;
> +}
> +
> +static const struct clk_ops loongson2_apb_clk_ops = {
> +	.recalc_rate = loongson2_apb_recalc_rate,
> +};
> +
> +static unsigned long loongson2_usb_recalc_rate(struct clk_hw *hw,
> +					  unsigned long parent_rate)
> +{
> +	u64 val;
> +	u32 mult;
> +	unsigned long rate;
> +
> +	val = readq((void *)(loongson2_pll_base + 0x50));
> +
> +	mult = (val >> LOONGSON2_USB_FREQSCALE_SHIFT) &
> +			clk_div_mask(LOONGSON2_USB_FREQSCALE_WIDTH);
> +
> +	rate = parent_rate * (mult + 1);
> +	do_div(rate, 8);
> +
> +	return rate;
> +}
> +
> +static const struct clk_ops loongson2_usb_clk_ops = {
> +	.recalc_rate = loongson2_usb_recalc_rate,
> +};
> +
> +static unsigned long loongson2_sata_recalc_rate(struct clk_hw *hw,
> +					  unsigned long parent_rate)
> +{
> +	u64 val;
> +	u32 mult;
> +	unsigned long rate;
> +
> +	val = readq((void *)(loongson2_pll_base + 0x50));
> +
> +	mult = (val >> LOONGSON2_SATA_FREQSCALE_SHIFT) &
> +			clk_div_mask(LOONGSON2_SATA_FREQSCALE_WIDTH);
> +
> +	rate = parent_rate * (mult + 1);
> +	do_div(rate, 8);
> +
> +	return rate;
> +}
> +

loongson2_sata_recalc_rate, loongson2_usb_recalc_rate,loongson2_apb_recalc_rate are have the same calcuate logic code, only the shift and width are different,
I thought it would be possible to abstract out a common function to reduce duplicate code

> +static const struct clk_ops loongson2_sata_clk_ops = {
> +	.recalc_rate = loongson2_sata_recalc_rate,
> +};
> +
> +static void loongson2_check_clk_hws(struct clk_hw *clks[], unsigned int count)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < count; i++)
> +		if (IS_ERR(clks[i]))
> +			pr_err("Loongson2 clk %u: register failed with %ld\n"
> +				, i, PTR_ERR(clks[i]));
> +}
> +
> +static struct clk_hw *loongson2_obtain_fixed_clk_hw(
> +					struct device_node *np,
> +					const char *name)
> +{
> +	struct clk *clk;
> +
> +	clk = of_clk_get_by_name(np, name);
> +	if (IS_ERR(clk))
> +		return ERR_PTR(-ENOENT);
> +
> +	return __clk_get_hw(clk);
> +}
> +
> +static void __init loongson2_clocks_init(struct device_node *np)
> +{
> +	struct clk_hw **hws;
> +	struct clk_hw_onecell_data *clk_hw_data;
> +	spinlock_t loongson2_clk_lock;
> +
> +	loongson2_pll_base = of_iomap(np, 0);
> +
> +	if (!loongson2_pll_base) {
> +		pr_err("clk: unable to map loongson2 clk registers\n");
> +		goto err;
> +	}
> +
> +	clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, LOONGSON2_CLK_END),
> +					GFP_KERNEL);
> +	if (WARN_ON(!clk_hw_data))
> +		goto err;
> +
> +	clk_hw_data->num = LOONGSON2_CLK_END;
> +	hws = clk_hw_data->hws;
> +
> +	hws[LOONGSON2_REF_100M] = loongson2_obtain_fixed_clk_hw(np,
> +						"ref_100m");
> +
> +	hws[LOONGSON2_NODE_PLL] = loongson2_clk_pll_register("node_pll",
> +						"ref_100m",
> +						loongson2_pll_base);
> +
> +	hws[LOONGSON2_DDR_PLL] = loongson2_clk_pll_register("ddr_pll",
> +						"ref_100m",
> +						loongson2_pll_base + 0x10);
> +
> +	hws[LOONGSON2_DC_PLL] = loongson2_clk_pll_register("dc_pll",
> +						"ref_100m",
> +						loongson2_pll_base + 0x20);
> +
> +	hws[LOONGSON2_PIX0_PLL] = loongson2_clk_pll_register("pix0_pll",
> +						"ref_100m",
> +						loongson2_pll_base + 0x30);
> +
> +	hws[LOONGSON2_PIX1_PLL] = loongson2_clk_pll_register("pix1_pll",
> +						"ref_100m",
> +						loongson2_pll_base + 0x40);
> +
> +	hws[LOONGSON2_NODE_CLK] = clk_hw_register_divider(NULL, "node",
> +						"node_pll", 0,
> +						loongson2_pll_base + 0x8, 0,
> +						6, CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	/*
> +	 * The hda clk divisor in the upper 32bits and the clk-prodiver
> +	 * layer code doesn't support 64bit io operation thus a conversion
> +	 * is required that subtract shift by 32 and add 4byte to the hda
> +	 * address
> +	 */
> +	hws[LOONGSON2_HDA_CLK] = clk_hw_register_divider(NULL, "hda",
> +						"ddr_pll", 0,
> +						loongson2_pll_base + 0x22, 12,
> +						7, CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	hws[LOONGSON2_GPU_CLK] = clk_hw_register_divider(NULL, "gpu",
> +						"ddr_pll", 0,
> +						loongson2_pll_base + 0x18, 22,
> +						6, CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	hws[LOONGSON2_DDR_CLK] = clk_hw_register_divider(NULL, "ddr",
> +						"ddr_pll", 0,
> +						loongson2_pll_base + 0x18, 0,
> +						6, CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	hws[LOONGSON2_GMAC_CLK] = clk_hw_register_divider(NULL, "gmac",
> +						"dc_pll", 0,
> +						loongson2_pll_base + 0x28, 22,
> +						6, CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	hws[LOONGSON2_DC_CLK] = clk_hw_register_divider(NULL, "dc",
> +						"dc_pll", 0,
> +						loongson2_pll_base + 0x28, 0,
> +						6, CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	hws[LOONGSON2_APB_CLK] = loongson2_clk_register(NULL, "apb",
> +						"gmac",
> +						&loongson2_apb_clk_ops, 0);
> +
> +	hws[LOONGSON2_USB_CLK] = loongson2_clk_register(NULL, "usb",
> +						"gmac",
> +						&loongson2_usb_clk_ops, 0);
> +
> +	hws[LOONGSON2_SATA_CLK] = loongson2_clk_register(NULL, "sata",
> +						"gmac",
> +						&loongson2_sata_clk_ops, 0);
> +
> +	hws[LOONGSON2_PIX0_CLK] = clk_hw_register_divider(NULL, "pix0",
> +						"pix0_pll", 0,
> +						loongson2_pll_base + 0x38, 0, 6,
> +						CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	hws[LOONGSON2_PIX1_CLK] = clk_hw_register_divider(NULL, "pix1",
> +						"pix1_pll", 0,
> +						loongson2_pll_base + 0x48, 0, 6,
> +						CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	loongson2_check_clk_hws(hws, LOONGSON2_CLK_END);
> +
> +	of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
> +
> +err:
> +	iounmap(loongson2_pll_base);
> +}
> +
> +CLK_OF_DECLARE(loongson2_clk, "loongson,ls2k-clk", loongson2_clocks_init);


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

* Re: [PATCH v10 2/4] clk: clk-loongson2: add clock controller driver support
  2022-11-30 13:14   ` XiaochuanMao
@ 2022-11-30 22:49     ` Yinbo Zhu
  0 siblings, 0 replies; 24+ messages in thread
From: Yinbo Zhu @ 2022-11-30 22:49 UTC (permalink / raw)
  To: XiaochuanMao, Michael Turquette, Stephen Boyd, Rob Herring,
	Krzysztof Kozlowski, Huacai Chen, WANG Xuerui, Jiaxun Yang,
	Jianmin Lv, Yang Li, linux-clk, devicetree, linux-kernel,
	loongarch


在 2022/11/30 21:14, XiaochuanMao 写道:
> hi yinbo
>
> On 2022/11/29 11:41, Yinbo Zhu wrote:
>> This driver provides support for clock controller on Loongson-2 SoC,
>> the Loongson-2 SoC uses a 100MHz clock as the PLL reference clock,
>> there are five independent PLLs inside, each of which PLL can
>> provide up to three sets of frequency dependent clock outputs.
>>
>> Signed-off-by: Yinbo Zhu <zhuyinbo@loongson.cn>
>> ---
>> Change in v10:
>>         1. Detach of_clk_init to another patch.
>> Change in v9:
>>         1. Add all history changelog information.
>> Change in v8:
>>         1. Remove the flag "CLK_IS_BASIC".
>> Change in v7:
>>         1. Adjust position alphabetically in Kconfig and Makefile.
>>         2. Add static for loongson2_pll_base.
>>         3. Move other file-scope variables in probe.
>> Change in v6:
>>         1. NO change, but other patch in this series of patches has
>>            changes.
>> Change in v5:
>>         1. Replace loongson2 with Loongson-2 in commit info.
>>         2. Replace Loongson2 with Loongson-2 in binding and
>>            Kconfig file.
>>         3. Replace soc with SoC.
>> Change in v4:
>>         1. Fixup clock-names that replace "xxx-clk" with "xxx".
>> Change in v3:
>>         1. NO change, but other patch in this series of patches has
>>            changes.
>> Change in v2:
>>         1. Update the include filename.
>>         2. Change string from refclk/REFCLK to ref/REF.
>>
>>   MAINTAINERS                 |   1 +
>>   arch/loongarch/Kconfig      |   1 +
>>   drivers/clk/Kconfig         |   9 ++
>>   drivers/clk/Makefile        |   1 +
>>   drivers/clk/clk-loongson2.c | 286 ++++++++++++++++++++++++++++++++++++
>>   5 files changed, 298 insertions(+)
>>   create mode 100644 drivers/clk/clk-loongson2.c
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index ab94893fe2f6..73fa56f1fd5d 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -12025,6 +12025,7 @@ LOONGSON-2 SOC SERIES CLOCK DRIVER
>>   M:    Yinbo Zhu <zhuyinbo@loongson.cn>
>>   L:    linux-clk@vger.kernel.org
>>   S:    Maintained
>> +F:    drivers/clk/clk-loongson2.c
>>   F:    include/dt-bindings/clock/loongson,ls2k-clk.h
>>     LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
>> diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
>> index 903096bd87f8..4f8f1b8f796d 100644
>> --- a/arch/loongarch/Kconfig
>> +++ b/arch/loongarch/Kconfig
>> @@ -127,6 +127,7 @@ config LOONGARCH
>>       select USE_PERCPU_NUMA_NODE_ID
>>       select USER_STACKTRACE_SUPPORT
>>       select ZONE_DMA32
>> +    select COMMON_CLK
>>     config 32BIT
>>       bool
>> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
>> index d79905f3e174..d13626f63739 100644
>> --- a/drivers/clk/Kconfig
>> +++ b/drivers/clk/Kconfig
>> @@ -326,6 +326,15 @@ config COMMON_CLK_LOCHNAGAR
>>         This driver supports the clocking features of the Cirrus Logic
>>         Lochnagar audio development board.
>>   +config COMMON_CLK_LOONGSON2
>> +    bool "Clock driver for Loongson-2 SoC"
>> +    depends on COMMON_CLK && OF
>> +    help
>> +      This driver provides support for Clock Controller that base on
>> +      Common Clock Framework Controller (CCF) on Loongson-2 SoC. The
>> +      Clock Controller can generates and supplies clock to various
>> +      peripherals within the SoC.
>> +
>>   config COMMON_CLK_NXP
>>       def_bool COMMON_CLK && (ARCH_LPC18XX || ARCH_LPC32XX)
>>       select REGMAP_MMIO if ARCH_LPC32XX
>> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>> index e3ca0d058a25..b298c5dabc1a 100644
>> --- a/drivers/clk/Makefile
>> +++ b/drivers/clk/Makefile
>> @@ -43,6 +43,7 @@ obj-$(CONFIG_COMMON_CLK_K210)        += clk-k210.o
>>   obj-$(CONFIG_LMK04832)            += clk-lmk04832.o
>>   obj-$(CONFIG_COMMON_CLK_LAN966X)    += clk-lan966x.o
>>   obj-$(CONFIG_COMMON_CLK_LOCHNAGAR)    += clk-lochnagar.o
>> +obj-$(CONFIG_COMMON_CLK_LOONGSON2)    += clk-loongson2.o
>>   obj-$(CONFIG_COMMON_CLK_MAX77686)    += clk-max77686.o
>>   obj-$(CONFIG_COMMON_CLK_MAX9485)    += clk-max9485.o
>>   obj-$(CONFIG_ARCH_MILBEAUT_M10V)    += clk-milbeaut.o
>> diff --git a/drivers/clk/clk-loongson2.c b/drivers/clk/clk-loongson2.c
>> new file mode 100644
>> index 000000000000..7487effceeab
>> --- /dev/null
>> +++ b/drivers/clk/clk-loongson2.c
>> @@ -0,0 +1,286 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * Author: Yinbo Zhu <zhuyinbo@loongson.cn>
>> + * Copyright (C) 2022-2023 Loongson Technology Corporation Limited
>> + */
>> +
>> +#include <linux/clkdev.h>
>> +#include <linux/err.h>
>> +#include <linux/init.h>
>> +#include <linux/of.h>
>> +#include <linux/of_address.h>
>> +#include <dt-bindings/clock/loongson,ls2k-clk.h>
>> +#include <linux/clk-provider.h>
>> +#include <linux/slab.h>
>> +#include <linux/clk.h>
>> +
>> +#define LOONGSON2_PLL_MULT_SHIFT        32
>> +#define LOONGSON2_PLL_MULT_WIDTH        10
>> +#define LOONGSON2_PLL_DIV_SHIFT            26
>> +#define LOONGSON2_PLL_DIV_WIDTH            6
>> +#define LOONGSON2_APB_FREQSCALE_SHIFT        20
>> +#define LOONGSON2_APB_FREQSCALE_WIDTH        3
>> +#define LOONGSON2_USB_FREQSCALE_SHIFT        16
>> +#define LOONGSON2_USB_FREQSCALE_WIDTH        3
>> +#define LOONGSON2_SATA_FREQSCALE_SHIFT        12
>> +#define LOONGSON2_SATA_FREQSCALE_WIDTH        3
>> +
>> +static void __iomem *loongson2_pll_base;
>> +
>> +static struct clk_hw *loongson2_clk_register(struct device *dev,
>> +                      const char *name,
>> +                      const char *parent_name,
>> +                      const struct clk_ops *ops,
>> +                      unsigned long flags)
>> +{
>> +    int ret;
>> +    struct clk_hw *hw;
>> +    struct clk_init_data init;
>> +
>> +    /* allocate the divider */
>> +    hw = kzalloc(sizeof(*hw), GFP_KERNEL);
>> +    if (!hw)
>> +        return ERR_PTR(-ENOMEM);
>> +
>> +    init.name = name;
>> +    init.ops = ops;
>> +    init.flags = flags;
>> +    init.parent_names = (parent_name ? &parent_name : NULL);
>> +    init.num_parents = (parent_name ? 1 : 0);
>> +    hw->init = &init;
>> +
>> +    /* register the clock */
>> +    ret = clk_hw_register(dev, hw);
>> +    if (ret) {
>> +        kfree(hw);
>> +        hw = ERR_PTR(ret);
>> +    }
>> +
>> +    return hw;
>> +}
>> +
>> +static struct clk_hw *loongson2_clk_pll_register(const char *name,
>> +                const char *parent, void __iomem *reg)
>> +{
>> +    u64 val;
>> +    u32 mult = 1, div = 1;
>> +
>> +    val = readq((void *)reg);
>> +
>> +    mult = (val >> LOONGSON2_PLL_MULT_SHIFT) &
>> +            clk_div_mask(LOONGSON2_PLL_MULT_WIDTH);
>> +    div = (val >> LOONGSON2_PLL_DIV_SHIFT) &
>> +            clk_div_mask(LOONGSON2_PLL_DIV_WIDTH);
>> +
>> +    return clk_hw_register_fixed_factor(NULL, name, parent,
>> +                CLK_SET_RATE_PARENT, mult, div);
>> +}
>> +
>> +static unsigned long loongson2_apb_recalc_rate(struct clk_hw *hw,
>> +                      unsigned long parent_rate)
>> +{
>> +    u64 val;
>> +    u32 mult;
>> +    unsigned long rate;
>> +
>> +    val = readq((void *)(loongson2_pll_base + 0x50));
>> +
>> +    mult = (val >> LOONGSON2_APB_FREQSCALE_SHIFT) &
>> +            clk_div_mask(LOONGSON2_APB_FREQSCALE_WIDTH);
>> +
>> +    rate = parent_rate * (mult + 1);
>> +    do_div(rate, 8);
>> +
>> +    return rate;
>> +}
>> +
>> +static const struct clk_ops loongson2_apb_clk_ops = {
>> +    .recalc_rate = loongson2_apb_recalc_rate,
>> +};
>> +
>> +static unsigned long loongson2_usb_recalc_rate(struct clk_hw *hw,
>> +                      unsigned long parent_rate)
>> +{
>> +    u64 val;
>> +    u32 mult;
>> +    unsigned long rate;
>> +
>> +    val = readq((void *)(loongson2_pll_base + 0x50));
>> +
>> +    mult = (val >> LOONGSON2_USB_FREQSCALE_SHIFT) &
>> +            clk_div_mask(LOONGSON2_USB_FREQSCALE_WIDTH);
>> +
>> +    rate = parent_rate * (mult + 1);
>> +    do_div(rate, 8);
>> +
>> +    return rate;
>> +}
>> +
>> +static const struct clk_ops loongson2_usb_clk_ops = {
>> +    .recalc_rate = loongson2_usb_recalc_rate,
>> +};
>> +
>> +static unsigned long loongson2_sata_recalc_rate(struct clk_hw *hw,
>> +                      unsigned long parent_rate)
>> +{
>> +    u64 val;
>> +    u32 mult;
>> +    unsigned long rate;
>> +
>> +    val = readq((void *)(loongson2_pll_base + 0x50));
>> +
>> +    mult = (val >> LOONGSON2_SATA_FREQSCALE_SHIFT) &
>> +            clk_div_mask(LOONGSON2_SATA_FREQSCALE_WIDTH);
>> +
>> +    rate = parent_rate * (mult + 1);
>> +    do_div(rate, 8);
>> +
>> +    return rate;
>> +}
>> +
>
> loongson2_sata_recalc_rate, 
> loongson2_usb_recalc_rate,loongson2_apb_recalc_rate are have the same 
> calcuate logic code, only the shift and width are different,
> I thought it would be possible to abstract out a common function to 
> reduce duplicate code

Thansk your advice, they are base on the same logic, I have noticed this 
at the begining,

  but I don't abstract it because the parameter of recalc_rate is fixed, 
and no other parameter

can be passed into it.


in fact, at the v1 version, I wanted to use a common interface to 
replace the logic of specific

implemetion,but the calculation of this clock was not standard, so I had 
to do this.

>
>> +static const struct clk_ops loongson2_sata_clk_ops = {
>> +    .recalc_rate = loongson2_sata_recalc_rate,
>> +};
>> +
>> +static void loongson2_check_clk_hws(struct clk_hw *clks[], unsigned 
>> int count)
>> +{
>> +    unsigned int i;
>> +
>> +    for (i = 0; i < count; i++)
>> +        if (IS_ERR(clks[i]))
>> +            pr_err("Loongson2 clk %u: register failed with %ld\n"
>> +                , i, PTR_ERR(clks[i]));
>> +}
>> +
>> +static struct clk_hw *loongson2_obtain_fixed_clk_hw(
>> +                    struct device_node *np,
>> +                    const char *name)
>> +{
>> +    struct clk *clk;
>> +
>> +    clk = of_clk_get_by_name(np, name);
>> +    if (IS_ERR(clk))
>> +        return ERR_PTR(-ENOENT);
>> +
>> +    return __clk_get_hw(clk);
>> +}
>> +
>> +static void __init loongson2_clocks_init(struct device_node *np)
>> +{
>> +    struct clk_hw **hws;
>> +    struct clk_hw_onecell_data *clk_hw_data;
>> +    spinlock_t loongson2_clk_lock;
>> +
>> +    loongson2_pll_base = of_iomap(np, 0);
>> +
>> +    if (!loongson2_pll_base) {
>> +        pr_err("clk: unable to map loongson2 clk registers\n");
>> +        goto err;
>> +    }
>> +
>> +    clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, 
>> LOONGSON2_CLK_END),
>> +                    GFP_KERNEL);
>> +    if (WARN_ON(!clk_hw_data))
>> +        goto err;
>> +
>> +    clk_hw_data->num = LOONGSON2_CLK_END;
>> +    hws = clk_hw_data->hws;
>> +
>> +    hws[LOONGSON2_REF_100M] = loongson2_obtain_fixed_clk_hw(np,
>> +                        "ref_100m");
>> +
>> +    hws[LOONGSON2_NODE_PLL] = loongson2_clk_pll_register("node_pll",
>> +                        "ref_100m",
>> +                        loongson2_pll_base);
>> +
>> +    hws[LOONGSON2_DDR_PLL] = loongson2_clk_pll_register("ddr_pll",
>> +                        "ref_100m",
>> +                        loongson2_pll_base + 0x10);
>> +
>> +    hws[LOONGSON2_DC_PLL] = loongson2_clk_pll_register("dc_pll",
>> +                        "ref_100m",
>> +                        loongson2_pll_base + 0x20);
>> +
>> +    hws[LOONGSON2_PIX0_PLL] = loongson2_clk_pll_register("pix0_pll",
>> +                        "ref_100m",
>> +                        loongson2_pll_base + 0x30);
>> +
>> +    hws[LOONGSON2_PIX1_PLL] = loongson2_clk_pll_register("pix1_pll",
>> +                        "ref_100m",
>> +                        loongson2_pll_base + 0x40);
>> +
>> +    hws[LOONGSON2_NODE_CLK] = clk_hw_register_divider(NULL, "node",
>> +                        "node_pll", 0,
>> +                        loongson2_pll_base + 0x8, 0,
>> +                        6, CLK_DIVIDER_ONE_BASED,
>> +                        &loongson2_clk_lock);
>> +
>> +    /*
>> +     * The hda clk divisor in the upper 32bits and the clk-prodiver
>> +     * layer code doesn't support 64bit io operation thus a conversion
>> +     * is required that subtract shift by 32 and add 4byte to the hda
>> +     * address
>> +     */
>> +    hws[LOONGSON2_HDA_CLK] = clk_hw_register_divider(NULL, "hda",
>> +                        "ddr_pll", 0,
>> +                        loongson2_pll_base + 0x22, 12,
>> +                        7, CLK_DIVIDER_ONE_BASED,
>> +                        &loongson2_clk_lock);
>> +
>> +    hws[LOONGSON2_GPU_CLK] = clk_hw_register_divider(NULL, "gpu",
>> +                        "ddr_pll", 0,
>> +                        loongson2_pll_base + 0x18, 22,
>> +                        6, CLK_DIVIDER_ONE_BASED,
>> +                        &loongson2_clk_lock);
>> +
>> +    hws[LOONGSON2_DDR_CLK] = clk_hw_register_divider(NULL, "ddr",
>> +                        "ddr_pll", 0,
>> +                        loongson2_pll_base + 0x18, 0,
>> +                        6, CLK_DIVIDER_ONE_BASED,
>> +                        &loongson2_clk_lock);
>> +
>> +    hws[LOONGSON2_GMAC_CLK] = clk_hw_register_divider(NULL, "gmac",
>> +                        "dc_pll", 0,
>> +                        loongson2_pll_base + 0x28, 22,
>> +                        6, CLK_DIVIDER_ONE_BASED,
>> +                        &loongson2_clk_lock);
>> +
>> +    hws[LOONGSON2_DC_CLK] = clk_hw_register_divider(NULL, "dc",
>> +                        "dc_pll", 0,
>> +                        loongson2_pll_base + 0x28, 0,
>> +                        6, CLK_DIVIDER_ONE_BASED,
>> +                        &loongson2_clk_lock);
>> +
>> +    hws[LOONGSON2_APB_CLK] = loongson2_clk_register(NULL, "apb",
>> +                        "gmac",
>> +                        &loongson2_apb_clk_ops, 0);
>> +
>> +    hws[LOONGSON2_USB_CLK] = loongson2_clk_register(NULL, "usb",
>> +                        "gmac",
>> +                        &loongson2_usb_clk_ops, 0);
>> +
>> +    hws[LOONGSON2_SATA_CLK] = loongson2_clk_register(NULL, "sata",
>> +                        "gmac",
>> +                        &loongson2_sata_clk_ops, 0);
>> +
>> +    hws[LOONGSON2_PIX0_CLK] = clk_hw_register_divider(NULL, "pix0",
>> +                        "pix0_pll", 0,
>> +                        loongson2_pll_base + 0x38, 0, 6,
>> +                        CLK_DIVIDER_ONE_BASED,
>> +                        &loongson2_clk_lock);
>> +
>> +    hws[LOONGSON2_PIX1_CLK] = clk_hw_register_divider(NULL, "pix1",
>> +                        "pix1_pll", 0,
>> +                        loongson2_pll_base + 0x48, 0, 6,
>> +                        CLK_DIVIDER_ONE_BASED,
>> +                        &loongson2_clk_lock);
>> +
>> +    loongson2_check_clk_hws(hws, LOONGSON2_CLK_END);
>> +
>> +    of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
>> +
>> +err:
>> +    iounmap(loongson2_pll_base);
>> +}
>> +
>> +CLK_OF_DECLARE(loongson2_clk, "loongson,ls2k-clk", 
>> loongson2_clocks_init);


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

* Re: [PATCH v10 2/4] clk: clk-loongson2: add clock controller driver support
  2022-11-29  3:41 ` [PATCH v10 2/4] clk: clk-loongson2: add clock controller driver support Yinbo Zhu
                     ` (2 preceding siblings ...)
  2022-11-30 13:14   ` XiaochuanMao
@ 2022-12-07  2:15   ` Yinbo Zhu
  2023-02-01  4:37   ` zhuyinbo
  2023-02-10 23:42   ` Stephen Boyd
  5 siblings, 0 replies; 24+ messages in thread
From: Yinbo Zhu @ 2022-12-07  2:15 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rob Herring,
	Krzysztof Kozlowski, Huacai Chen, WANG Xuerui, Jiaxun Yang,
	Jianmin Lv, Yang Li, linux-clk, devicetree, linux-kernel,
	loongarch

Hi clock maintainer,


Could you help me merge this series patch.


Thanks.

在 2022/11/29 11:41, Yinbo Zhu 写道:
> This driver provides support for clock controller on Loongson-2 SoC,
> the Loongson-2 SoC uses a 100MHz clock as the PLL reference clock,
> there are five independent PLLs inside, each of which PLL can
> provide up to three sets of frequency dependent clock outputs.
>
> Signed-off-by: Yinbo Zhu <zhuyinbo@loongson.cn>
> ---
> Change in v10:
> 		1. Detach of_clk_init to another patch.
> Change in v9:
> 		1. Add all history changelog information.
> Change in v8:
> 		1. Remove the flag "CLK_IS_BASIC".
> Change in v7:
> 		1. Adjust position alphabetically in Kconfig and Makefile.
> 		2. Add static for loongson2_pll_base.
> 		3. Move other file-scope variables in probe.
> Change in v6:
> 		1. NO change, but other patch in this series of patches has
> 		   changes.
> Change in v5:
> 		1. Replace loongson2 with Loongson-2 in commit info.
> 		2. Replace Loongson2 with Loongson-2 in binding and
> 		   Kconfig file.
> 		3. Replace soc with SoC.
> Change in v4:
> 		1. Fixup clock-names that replace "xxx-clk" with "xxx".
> Change in v3:
> 		1. NO change, but other patch in this series of patches has
> 		   changes.
> Change in v2:
> 		1. Update the include filename.
> 		2. Change string from refclk/REFCLK to ref/REF.
>
>   MAINTAINERS                 |   1 +
>   arch/loongarch/Kconfig      |   1 +
>   drivers/clk/Kconfig         |   9 ++
>   drivers/clk/Makefile        |   1 +
>   drivers/clk/clk-loongson2.c | 286 ++++++++++++++++++++++++++++++++++++
>   5 files changed, 298 insertions(+)
>   create mode 100644 drivers/clk/clk-loongson2.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index ab94893fe2f6..73fa56f1fd5d 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -12025,6 +12025,7 @@ LOONGSON-2 SOC SERIES CLOCK DRIVER
>   M:	Yinbo Zhu <zhuyinbo@loongson.cn>
>   L:	linux-clk@vger.kernel.org
>   S:	Maintained
> +F:	drivers/clk/clk-loongson2.c
>   F:	include/dt-bindings/clock/loongson,ls2k-clk.h
>   
>   LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
> diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
> index 903096bd87f8..4f8f1b8f796d 100644
> --- a/arch/loongarch/Kconfig
> +++ b/arch/loongarch/Kconfig
> @@ -127,6 +127,7 @@ config LOONGARCH
>   	select USE_PERCPU_NUMA_NODE_ID
>   	select USER_STACKTRACE_SUPPORT
>   	select ZONE_DMA32
> +	select COMMON_CLK
>   
>   config 32BIT
>   	bool
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index d79905f3e174..d13626f63739 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -326,6 +326,15 @@ config COMMON_CLK_LOCHNAGAR
>   	  This driver supports the clocking features of the Cirrus Logic
>   	  Lochnagar audio development board.
>   
> +config COMMON_CLK_LOONGSON2
> +	bool "Clock driver for Loongson-2 SoC"
> +	depends on COMMON_CLK && OF
> +	help
> +	  This driver provides support for Clock Controller that base on
> +	  Common Clock Framework Controller (CCF) on Loongson-2 SoC. The
> +	  Clock Controller can generates and supplies clock to various
> +	  peripherals within the SoC.
> +
>   config COMMON_CLK_NXP
>   	def_bool COMMON_CLK && (ARCH_LPC18XX || ARCH_LPC32XX)
>   	select REGMAP_MMIO if ARCH_LPC32XX
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index e3ca0d058a25..b298c5dabc1a 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -43,6 +43,7 @@ obj-$(CONFIG_COMMON_CLK_K210)		+= clk-k210.o
>   obj-$(CONFIG_LMK04832)			+= clk-lmk04832.o
>   obj-$(CONFIG_COMMON_CLK_LAN966X)	+= clk-lan966x.o
>   obj-$(CONFIG_COMMON_CLK_LOCHNAGAR)	+= clk-lochnagar.o
> +obj-$(CONFIG_COMMON_CLK_LOONGSON2)	+= clk-loongson2.o
>   obj-$(CONFIG_COMMON_CLK_MAX77686)	+= clk-max77686.o
>   obj-$(CONFIG_COMMON_CLK_MAX9485)	+= clk-max9485.o
>   obj-$(CONFIG_ARCH_MILBEAUT_M10V)	+= clk-milbeaut.o
> diff --git a/drivers/clk/clk-loongson2.c b/drivers/clk/clk-loongson2.c
> new file mode 100644
> index 000000000000..7487effceeab
> --- /dev/null
> +++ b/drivers/clk/clk-loongson2.c
> @@ -0,0 +1,286 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Author: Yinbo Zhu <zhuyinbo@loongson.cn>
> + * Copyright (C) 2022-2023 Loongson Technology Corporation Limited
> + */
> +
> +#include <linux/clkdev.h>
> +#include <linux/err.h>
> +#include <linux/init.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <dt-bindings/clock/loongson,ls2k-clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/slab.h>
> +#include <linux/clk.h>
> +
> +#define LOONGSON2_PLL_MULT_SHIFT		32
> +#define LOONGSON2_PLL_MULT_WIDTH		10
> +#define LOONGSON2_PLL_DIV_SHIFT			26
> +#define LOONGSON2_PLL_DIV_WIDTH			6
> +#define LOONGSON2_APB_FREQSCALE_SHIFT		20
> +#define LOONGSON2_APB_FREQSCALE_WIDTH		3
> +#define LOONGSON2_USB_FREQSCALE_SHIFT		16
> +#define LOONGSON2_USB_FREQSCALE_WIDTH		3
> +#define LOONGSON2_SATA_FREQSCALE_SHIFT		12
> +#define LOONGSON2_SATA_FREQSCALE_WIDTH		3
> +
> +static void __iomem *loongson2_pll_base;
> +
> +static struct clk_hw *loongson2_clk_register(struct device *dev,
> +					  const char *name,
> +					  const char *parent_name,
> +					  const struct clk_ops *ops,
> +					  unsigned long flags)
> +{
> +	int ret;
> +	struct clk_hw *hw;
> +	struct clk_init_data init;
> +
> +	/* allocate the divider */
> +	hw = kzalloc(sizeof(*hw), GFP_KERNEL);
> +	if (!hw)
> +		return ERR_PTR(-ENOMEM);
> +
> +	init.name = name;
> +	init.ops = ops;
> +	init.flags = flags;
> +	init.parent_names = (parent_name ? &parent_name : NULL);
> +	init.num_parents = (parent_name ? 1 : 0);
> +	hw->init = &init;
> +
> +	/* register the clock */
> +	ret = clk_hw_register(dev, hw);
> +	if (ret) {
> +		kfree(hw);
> +		hw = ERR_PTR(ret);
> +	}
> +
> +	return hw;
> +}
> +
> +static struct clk_hw *loongson2_clk_pll_register(const char *name,
> +				const char *parent, void __iomem *reg)
> +{
> +	u64 val;
> +	u32 mult = 1, div = 1;
> +
> +	val = readq((void *)reg);
> +
> +	mult = (val >> LOONGSON2_PLL_MULT_SHIFT) &
> +			clk_div_mask(LOONGSON2_PLL_MULT_WIDTH);
> +	div = (val >> LOONGSON2_PLL_DIV_SHIFT) &
> +			clk_div_mask(LOONGSON2_PLL_DIV_WIDTH);
> +
> +	return clk_hw_register_fixed_factor(NULL, name, parent,
> +				CLK_SET_RATE_PARENT, mult, div);
> +}
> +
> +static unsigned long loongson2_apb_recalc_rate(struct clk_hw *hw,
> +					  unsigned long parent_rate)
> +{
> +	u64 val;
> +	u32 mult;
> +	unsigned long rate;
> +
> +	val = readq((void *)(loongson2_pll_base + 0x50));
> +
> +	mult = (val >> LOONGSON2_APB_FREQSCALE_SHIFT) &
> +			clk_div_mask(LOONGSON2_APB_FREQSCALE_WIDTH);
> +
> +	rate = parent_rate * (mult + 1);
> +	do_div(rate, 8);
> +
> +	return rate;
> +}
> +
> +static const struct clk_ops loongson2_apb_clk_ops = {
> +	.recalc_rate = loongson2_apb_recalc_rate,
> +};
> +
> +static unsigned long loongson2_usb_recalc_rate(struct clk_hw *hw,
> +					  unsigned long parent_rate)
> +{
> +	u64 val;
> +	u32 mult;
> +	unsigned long rate;
> +
> +	val = readq((void *)(loongson2_pll_base + 0x50));
> +
> +	mult = (val >> LOONGSON2_USB_FREQSCALE_SHIFT) &
> +			clk_div_mask(LOONGSON2_USB_FREQSCALE_WIDTH);
> +
> +	rate = parent_rate * (mult + 1);
> +	do_div(rate, 8);
> +
> +	return rate;
> +}
> +
> +static const struct clk_ops loongson2_usb_clk_ops = {
> +	.recalc_rate = loongson2_usb_recalc_rate,
> +};
> +
> +static unsigned long loongson2_sata_recalc_rate(struct clk_hw *hw,
> +					  unsigned long parent_rate)
> +{
> +	u64 val;
> +	u32 mult;
> +	unsigned long rate;
> +
> +	val = readq((void *)(loongson2_pll_base + 0x50));
> +
> +	mult = (val >> LOONGSON2_SATA_FREQSCALE_SHIFT) &
> +			clk_div_mask(LOONGSON2_SATA_FREQSCALE_WIDTH);
> +
> +	rate = parent_rate * (mult + 1);
> +	do_div(rate, 8);
> +
> +	return rate;
> +}
> +
> +static const struct clk_ops loongson2_sata_clk_ops = {
> +	.recalc_rate = loongson2_sata_recalc_rate,
> +};
> +
> +static void loongson2_check_clk_hws(struct clk_hw *clks[], unsigned int count)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < count; i++)
> +		if (IS_ERR(clks[i]))
> +			pr_err("Loongson2 clk %u: register failed with %ld\n"
> +				, i, PTR_ERR(clks[i]));
> +}
> +
> +static struct clk_hw *loongson2_obtain_fixed_clk_hw(
> +					struct device_node *np,
> +					const char *name)
> +{
> +	struct clk *clk;
> +
> +	clk = of_clk_get_by_name(np, name);
> +	if (IS_ERR(clk))
> +		return ERR_PTR(-ENOENT);
> +
> +	return __clk_get_hw(clk);
> +}
> +
> +static void __init loongson2_clocks_init(struct device_node *np)
> +{
> +	struct clk_hw **hws;
> +	struct clk_hw_onecell_data *clk_hw_data;
> +	spinlock_t loongson2_clk_lock;
> +
> +	loongson2_pll_base = of_iomap(np, 0);
> +
> +	if (!loongson2_pll_base) {
> +		pr_err("clk: unable to map loongson2 clk registers\n");
> +		goto err;
> +	}
> +
> +	clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, LOONGSON2_CLK_END),
> +					GFP_KERNEL);
> +	if (WARN_ON(!clk_hw_data))
> +		goto err;
> +
> +	clk_hw_data->num = LOONGSON2_CLK_END;
> +	hws = clk_hw_data->hws;
> +
> +	hws[LOONGSON2_REF_100M] = loongson2_obtain_fixed_clk_hw(np,
> +						"ref_100m");
> +
> +	hws[LOONGSON2_NODE_PLL] = loongson2_clk_pll_register("node_pll",
> +						"ref_100m",
> +						loongson2_pll_base);
> +
> +	hws[LOONGSON2_DDR_PLL] = loongson2_clk_pll_register("ddr_pll",
> +						"ref_100m",
> +						loongson2_pll_base + 0x10);
> +
> +	hws[LOONGSON2_DC_PLL] = loongson2_clk_pll_register("dc_pll",
> +						"ref_100m",
> +						loongson2_pll_base + 0x20);
> +
> +	hws[LOONGSON2_PIX0_PLL] = loongson2_clk_pll_register("pix0_pll",
> +						"ref_100m",
> +						loongson2_pll_base + 0x30);
> +
> +	hws[LOONGSON2_PIX1_PLL] = loongson2_clk_pll_register("pix1_pll",
> +						"ref_100m",
> +						loongson2_pll_base + 0x40);
> +
> +	hws[LOONGSON2_NODE_CLK] = clk_hw_register_divider(NULL, "node",
> +						"node_pll", 0,
> +						loongson2_pll_base + 0x8, 0,
> +						6, CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	/*
> +	 * The hda clk divisor in the upper 32bits and the clk-prodiver
> +	 * layer code doesn't support 64bit io operation thus a conversion
> +	 * is required that subtract shift by 32 and add 4byte to the hda
> +	 * address
> +	 */
> +	hws[LOONGSON2_HDA_CLK] = clk_hw_register_divider(NULL, "hda",
> +						"ddr_pll", 0,
> +						loongson2_pll_base + 0x22, 12,
> +						7, CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	hws[LOONGSON2_GPU_CLK] = clk_hw_register_divider(NULL, "gpu",
> +						"ddr_pll", 0,
> +						loongson2_pll_base + 0x18, 22,
> +						6, CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	hws[LOONGSON2_DDR_CLK] = clk_hw_register_divider(NULL, "ddr",
> +						"ddr_pll", 0,
> +						loongson2_pll_base + 0x18, 0,
> +						6, CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	hws[LOONGSON2_GMAC_CLK] = clk_hw_register_divider(NULL, "gmac",
> +						"dc_pll", 0,
> +						loongson2_pll_base + 0x28, 22,
> +						6, CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	hws[LOONGSON2_DC_CLK] = clk_hw_register_divider(NULL, "dc",
> +						"dc_pll", 0,
> +						loongson2_pll_base + 0x28, 0,
> +						6, CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	hws[LOONGSON2_APB_CLK] = loongson2_clk_register(NULL, "apb",
> +						"gmac",
> +						&loongson2_apb_clk_ops, 0);
> +
> +	hws[LOONGSON2_USB_CLK] = loongson2_clk_register(NULL, "usb",
> +						"gmac",
> +						&loongson2_usb_clk_ops, 0);
> +
> +	hws[LOONGSON2_SATA_CLK] = loongson2_clk_register(NULL, "sata",
> +						"gmac",
> +						&loongson2_sata_clk_ops, 0);
> +
> +	hws[LOONGSON2_PIX0_CLK] = clk_hw_register_divider(NULL, "pix0",
> +						"pix0_pll", 0,
> +						loongson2_pll_base + 0x38, 0, 6,
> +						CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	hws[LOONGSON2_PIX1_CLK] = clk_hw_register_divider(NULL, "pix1",
> +						"pix1_pll", 0,
> +						loongson2_pll_base + 0x48, 0, 6,
> +						CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	loongson2_check_clk_hws(hws, LOONGSON2_CLK_END);
> +
> +	of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
> +
> +err:
> +	iounmap(loongson2_pll_base);
> +}
> +
> +CLK_OF_DECLARE(loongson2_clk, "loongson,ls2k-clk", loongson2_clocks_init);


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

* Re: [PATCH v10 2/4] clk: clk-loongson2: add clock controller driver support
  2022-11-29  3:41 ` [PATCH v10 2/4] clk: clk-loongson2: add clock controller driver support Yinbo Zhu
                     ` (3 preceding siblings ...)
  2022-12-07  2:15   ` Yinbo Zhu
@ 2023-02-01  4:37   ` zhuyinbo
  2023-02-10 23:42   ` Stephen Boyd
  5 siblings, 0 replies; 24+ messages in thread
From: zhuyinbo @ 2023-02-01  4:37 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rob Herring,
	Krzysztof Kozlowski, Huacai Chen, WANG Xuerui, Jiaxun Yang,
	Jianmin Lv, Yang Li, linux-clk, devicetree, linux-kernel,
	loongarch, lvjianmin, wanghongliang, liupeibao, zhuyinbo


Friendly ping ?


在 2022/11/29 上午11:41, Yinbo Zhu 写道:
> This driver provides support for clock controller on Loongson-2 SoC,
> the Loongson-2 SoC uses a 100MHz clock as the PLL reference clock,
> there are five independent PLLs inside, each of which PLL can
> provide up to three sets of frequency dependent clock outputs.
>
> Signed-off-by: Yinbo Zhu <zhuyinbo@loongson.cn>
> ---
> Change in v10:
> 		1. Detach of_clk_init to another patch.
> Change in v9:
> 		1. Add all history changelog information.
> Change in v8:
> 		1. Remove the flag "CLK_IS_BASIC".
> Change in v7:
> 		1. Adjust position alphabetically in Kconfig and Makefile.
> 		2. Add static for loongson2_pll_base.
> 		3. Move other file-scope variables in probe.
> Change in v6:
> 		1. NO change, but other patch in this series of patches has
> 		   changes.
> Change in v5:
> 		1. Replace loongson2 with Loongson-2 in commit info.
> 		2. Replace Loongson2 with Loongson-2 in binding and
> 		   Kconfig file.
> 		3. Replace soc with SoC.
> Change in v4:
> 		1. Fixup clock-names that replace "xxx-clk" with "xxx".
> Change in v3:
> 		1. NO change, but other patch in this series of patches has
> 		   changes.
> Change in v2:
> 		1. Update the include filename.
> 		2. Change string from refclk/REFCLK to ref/REF.
>
>   MAINTAINERS                 |   1 +
>   arch/loongarch/Kconfig      |   1 +
>   drivers/clk/Kconfig         |   9 ++
>   drivers/clk/Makefile        |   1 +
>   drivers/clk/clk-loongson2.c | 286 ++++++++++++++++++++++++++++++++++++
>   5 files changed, 298 insertions(+)
>   create mode 100644 drivers/clk/clk-loongson2.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index ab94893fe2f6..73fa56f1fd5d 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -12025,6 +12025,7 @@ LOONGSON-2 SOC SERIES CLOCK DRIVER
>   M:	Yinbo Zhu <zhuyinbo@loongson.cn>
>   L:	linux-clk@vger.kernel.org
>   S:	Maintained
> +F:	drivers/clk/clk-loongson2.c
>   F:	include/dt-bindings/clock/loongson,ls2k-clk.h
>   
>   LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
> diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
> index 903096bd87f8..4f8f1b8f796d 100644
> --- a/arch/loongarch/Kconfig
> +++ b/arch/loongarch/Kconfig
> @@ -127,6 +127,7 @@ config LOONGARCH
>   	select USE_PERCPU_NUMA_NODE_ID
>   	select USER_STACKTRACE_SUPPORT
>   	select ZONE_DMA32
> +	select COMMON_CLK
>   
>   config 32BIT
>   	bool
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index d79905f3e174..d13626f63739 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -326,6 +326,15 @@ config COMMON_CLK_LOCHNAGAR
>   	  This driver supports the clocking features of the Cirrus Logic
>   	  Lochnagar audio development board.
>   
> +config COMMON_CLK_LOONGSON2
> +	bool "Clock driver for Loongson-2 SoC"
> +	depends on COMMON_CLK && OF
> +	help
> +	  This driver provides support for Clock Controller that base on
> +	  Common Clock Framework Controller (CCF) on Loongson-2 SoC. The
> +	  Clock Controller can generates and supplies clock to various
> +	  peripherals within the SoC.
> +
>   config COMMON_CLK_NXP
>   	def_bool COMMON_CLK && (ARCH_LPC18XX || ARCH_LPC32XX)
>   	select REGMAP_MMIO if ARCH_LPC32XX
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index e3ca0d058a25..b298c5dabc1a 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -43,6 +43,7 @@ obj-$(CONFIG_COMMON_CLK_K210)		+= clk-k210.o
>   obj-$(CONFIG_LMK04832)			+= clk-lmk04832.o
>   obj-$(CONFIG_COMMON_CLK_LAN966X)	+= clk-lan966x.o
>   obj-$(CONFIG_COMMON_CLK_LOCHNAGAR)	+= clk-lochnagar.o
> +obj-$(CONFIG_COMMON_CLK_LOONGSON2)	+= clk-loongson2.o
>   obj-$(CONFIG_COMMON_CLK_MAX77686)	+= clk-max77686.o
>   obj-$(CONFIG_COMMON_CLK_MAX9485)	+= clk-max9485.o
>   obj-$(CONFIG_ARCH_MILBEAUT_M10V)	+= clk-milbeaut.o
> diff --git a/drivers/clk/clk-loongson2.c b/drivers/clk/clk-loongson2.c
> new file mode 100644
> index 000000000000..7487effceeab
> --- /dev/null
> +++ b/drivers/clk/clk-loongson2.c
> @@ -0,0 +1,286 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Author: Yinbo Zhu <zhuyinbo@loongson.cn>
> + * Copyright (C) 2022-2023 Loongson Technology Corporation Limited
> + */
> +
> +#include <linux/clkdev.h>
> +#include <linux/err.h>
> +#include <linux/init.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <dt-bindings/clock/loongson,ls2k-clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/slab.h>
> +#include <linux/clk.h>
> +
> +#define LOONGSON2_PLL_MULT_SHIFT		32
> +#define LOONGSON2_PLL_MULT_WIDTH		10
> +#define LOONGSON2_PLL_DIV_SHIFT			26
> +#define LOONGSON2_PLL_DIV_WIDTH			6
> +#define LOONGSON2_APB_FREQSCALE_SHIFT		20
> +#define LOONGSON2_APB_FREQSCALE_WIDTH		3
> +#define LOONGSON2_USB_FREQSCALE_SHIFT		16
> +#define LOONGSON2_USB_FREQSCALE_WIDTH		3
> +#define LOONGSON2_SATA_FREQSCALE_SHIFT		12
> +#define LOONGSON2_SATA_FREQSCALE_WIDTH		3
> +
> +static void __iomem *loongson2_pll_base;
> +
> +static struct clk_hw *loongson2_clk_register(struct device *dev,
> +					  const char *name,
> +					  const char *parent_name,
> +					  const struct clk_ops *ops,
> +					  unsigned long flags)
> +{
> +	int ret;
> +	struct clk_hw *hw;
> +	struct clk_init_data init;
> +
> +	/* allocate the divider */
> +	hw = kzalloc(sizeof(*hw), GFP_KERNEL);
> +	if (!hw)
> +		return ERR_PTR(-ENOMEM);
> +
> +	init.name = name;
> +	init.ops = ops;
> +	init.flags = flags;
> +	init.parent_names = (parent_name ? &parent_name : NULL);
> +	init.num_parents = (parent_name ? 1 : 0);
> +	hw->init = &init;
> +
> +	/* register the clock */
> +	ret = clk_hw_register(dev, hw);
> +	if (ret) {
> +		kfree(hw);
> +		hw = ERR_PTR(ret);
> +	}
> +
> +	return hw;
> +}
> +
> +static struct clk_hw *loongson2_clk_pll_register(const char *name,
> +				const char *parent, void __iomem *reg)
> +{
> +	u64 val;
> +	u32 mult = 1, div = 1;
> +
> +	val = readq((void *)reg);
> +
> +	mult = (val >> LOONGSON2_PLL_MULT_SHIFT) &
> +			clk_div_mask(LOONGSON2_PLL_MULT_WIDTH);
> +	div = (val >> LOONGSON2_PLL_DIV_SHIFT) &
> +			clk_div_mask(LOONGSON2_PLL_DIV_WIDTH);
> +
> +	return clk_hw_register_fixed_factor(NULL, name, parent,
> +				CLK_SET_RATE_PARENT, mult, div);
> +}
> +
> +static unsigned long loongson2_apb_recalc_rate(struct clk_hw *hw,
> +					  unsigned long parent_rate)
> +{
> +	u64 val;
> +	u32 mult;
> +	unsigned long rate;
> +
> +	val = readq((void *)(loongson2_pll_base + 0x50));
> +
> +	mult = (val >> LOONGSON2_APB_FREQSCALE_SHIFT) &
> +			clk_div_mask(LOONGSON2_APB_FREQSCALE_WIDTH);
> +
> +	rate = parent_rate * (mult + 1);
> +	do_div(rate, 8);
> +
> +	return rate;
> +}
> +
> +static const struct clk_ops loongson2_apb_clk_ops = {
> +	.recalc_rate = loongson2_apb_recalc_rate,
> +};
> +
> +static unsigned long loongson2_usb_recalc_rate(struct clk_hw *hw,
> +					  unsigned long parent_rate)
> +{
> +	u64 val;
> +	u32 mult;
> +	unsigned long rate;
> +
> +	val = readq((void *)(loongson2_pll_base + 0x50));
> +
> +	mult = (val >> LOONGSON2_USB_FREQSCALE_SHIFT) &
> +			clk_div_mask(LOONGSON2_USB_FREQSCALE_WIDTH);
> +
> +	rate = parent_rate * (mult + 1);
> +	do_div(rate, 8);
> +
> +	return rate;
> +}
> +
> +static const struct clk_ops loongson2_usb_clk_ops = {
> +	.recalc_rate = loongson2_usb_recalc_rate,
> +};
> +
> +static unsigned long loongson2_sata_recalc_rate(struct clk_hw *hw,
> +					  unsigned long parent_rate)
> +{
> +	u64 val;
> +	u32 mult;
> +	unsigned long rate;
> +
> +	val = readq((void *)(loongson2_pll_base + 0x50));
> +
> +	mult = (val >> LOONGSON2_SATA_FREQSCALE_SHIFT) &
> +			clk_div_mask(LOONGSON2_SATA_FREQSCALE_WIDTH);
> +
> +	rate = parent_rate * (mult + 1);
> +	do_div(rate, 8);
> +
> +	return rate;
> +}
> +
> +static const struct clk_ops loongson2_sata_clk_ops = {
> +	.recalc_rate = loongson2_sata_recalc_rate,
> +};
> +
> +static void loongson2_check_clk_hws(struct clk_hw *clks[], unsigned int count)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < count; i++)
> +		if (IS_ERR(clks[i]))
> +			pr_err("Loongson2 clk %u: register failed with %ld\n"
> +				, i, PTR_ERR(clks[i]));
> +}
> +
> +static struct clk_hw *loongson2_obtain_fixed_clk_hw(
> +					struct device_node *np,
> +					const char *name)
> +{
> +	struct clk *clk;
> +
> +	clk = of_clk_get_by_name(np, name);
> +	if (IS_ERR(clk))
> +		return ERR_PTR(-ENOENT);
> +
> +	return __clk_get_hw(clk);
> +}
> +
> +static void __init loongson2_clocks_init(struct device_node *np)
> +{
> +	struct clk_hw **hws;
> +	struct clk_hw_onecell_data *clk_hw_data;
> +	spinlock_t loongson2_clk_lock;
> +
> +	loongson2_pll_base = of_iomap(np, 0);
> +
> +	if (!loongson2_pll_base) {
> +		pr_err("clk: unable to map loongson2 clk registers\n");
> +		goto err;
> +	}
> +
> +	clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, LOONGSON2_CLK_END),
> +					GFP_KERNEL);
> +	if (WARN_ON(!clk_hw_data))
> +		goto err;
> +
> +	clk_hw_data->num = LOONGSON2_CLK_END;
> +	hws = clk_hw_data->hws;
> +
> +	hws[LOONGSON2_REF_100M] = loongson2_obtain_fixed_clk_hw(np,
> +						"ref_100m");
> +
> +	hws[LOONGSON2_NODE_PLL] = loongson2_clk_pll_register("node_pll",
> +						"ref_100m",
> +						loongson2_pll_base);
> +
> +	hws[LOONGSON2_DDR_PLL] = loongson2_clk_pll_register("ddr_pll",
> +						"ref_100m",
> +						loongson2_pll_base + 0x10);
> +
> +	hws[LOONGSON2_DC_PLL] = loongson2_clk_pll_register("dc_pll",
> +						"ref_100m",
> +						loongson2_pll_base + 0x20);
> +
> +	hws[LOONGSON2_PIX0_PLL] = loongson2_clk_pll_register("pix0_pll",
> +						"ref_100m",
> +						loongson2_pll_base + 0x30);
> +
> +	hws[LOONGSON2_PIX1_PLL] = loongson2_clk_pll_register("pix1_pll",
> +						"ref_100m",
> +						loongson2_pll_base + 0x40);
> +
> +	hws[LOONGSON2_NODE_CLK] = clk_hw_register_divider(NULL, "node",
> +						"node_pll", 0,
> +						loongson2_pll_base + 0x8, 0,
> +						6, CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	/*
> +	 * The hda clk divisor in the upper 32bits and the clk-prodiver
> +	 * layer code doesn't support 64bit io operation thus a conversion
> +	 * is required that subtract shift by 32 and add 4byte to the hda
> +	 * address
> +	 */
> +	hws[LOONGSON2_HDA_CLK] = clk_hw_register_divider(NULL, "hda",
> +						"ddr_pll", 0,
> +						loongson2_pll_base + 0x22, 12,
> +						7, CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	hws[LOONGSON2_GPU_CLK] = clk_hw_register_divider(NULL, "gpu",
> +						"ddr_pll", 0,
> +						loongson2_pll_base + 0x18, 22,
> +						6, CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	hws[LOONGSON2_DDR_CLK] = clk_hw_register_divider(NULL, "ddr",
> +						"ddr_pll", 0,
> +						loongson2_pll_base + 0x18, 0,
> +						6, CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	hws[LOONGSON2_GMAC_CLK] = clk_hw_register_divider(NULL, "gmac",
> +						"dc_pll", 0,
> +						loongson2_pll_base + 0x28, 22,
> +						6, CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	hws[LOONGSON2_DC_CLK] = clk_hw_register_divider(NULL, "dc",
> +						"dc_pll", 0,
> +						loongson2_pll_base + 0x28, 0,
> +						6, CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	hws[LOONGSON2_APB_CLK] = loongson2_clk_register(NULL, "apb",
> +						"gmac",
> +						&loongson2_apb_clk_ops, 0);
> +
> +	hws[LOONGSON2_USB_CLK] = loongson2_clk_register(NULL, "usb",
> +						"gmac",
> +						&loongson2_usb_clk_ops, 0);
> +
> +	hws[LOONGSON2_SATA_CLK] = loongson2_clk_register(NULL, "sata",
> +						"gmac",
> +						&loongson2_sata_clk_ops, 0);
> +
> +	hws[LOONGSON2_PIX0_CLK] = clk_hw_register_divider(NULL, "pix0",
> +						"pix0_pll", 0,
> +						loongson2_pll_base + 0x38, 0, 6,
> +						CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	hws[LOONGSON2_PIX1_CLK] = clk_hw_register_divider(NULL, "pix1",
> +						"pix1_pll", 0,
> +						loongson2_pll_base + 0x48, 0, 6,
> +						CLK_DIVIDER_ONE_BASED,
> +						&loongson2_clk_lock);
> +
> +	loongson2_check_clk_hws(hws, LOONGSON2_CLK_END);
> +
> +	of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
> +
> +err:
> +	iounmap(loongson2_pll_base);
> +}
> +
> +CLK_OF_DECLARE(loongson2_clk, "loongson,ls2k-clk", loongson2_clocks_init);


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

* Re: [PATCH v10 3/4] LoongArch: time: add of_clk_init in time_init
  2022-11-29  3:41 ` [PATCH v10 3/4] LoongArch: time: add of_clk_init in time_init Yinbo Zhu
@ 2023-02-10 23:33   ` Stephen Boyd
  0 siblings, 0 replies; 24+ messages in thread
From: Stephen Boyd @ 2023-02-10 23:33 UTC (permalink / raw)
  To: Huacai Chen, Jianmin Lv, Jiaxun Yang, Krzysztof Kozlowski,
	Michael Turquette, Rob Herring, WANG Xuerui, Yang Li, Yinbo Zhu,
	devicetree, linux-clk, linux-kernel, loongarch

Quoting Yinbo Zhu (2022-11-28 19:41:56)
> The Loongson-2 clock controller driver used CLK_OF_DECLARE to
> register clock subsystem that ask of_clk_init was called in
> time_init and this patch was to addd such support.
> 
> Signed-off-by: Yinbo Zhu <zhuyinbo@loongson.cn>
> ---

Acked-by: Stephen Boyd <sboyd@kernel.org>

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

* Re: [PATCH v10 2/4] clk: clk-loongson2: add clock controller driver support
  2022-11-29  3:41 ` [PATCH v10 2/4] clk: clk-loongson2: add clock controller driver support Yinbo Zhu
                     ` (4 preceding siblings ...)
  2023-02-01  4:37   ` zhuyinbo
@ 2023-02-10 23:42   ` Stephen Boyd
  2023-02-15  7:35     ` zhuyinbo
  5 siblings, 1 reply; 24+ messages in thread
From: Stephen Boyd @ 2023-02-10 23:42 UTC (permalink / raw)
  To: Huacai Chen, Jianmin Lv, Jiaxun Yang, Krzysztof Kozlowski,
	Michael Turquette, Rob Herring, WANG Xuerui, Yang Li, Yinbo Zhu,
	devicetree, linux-clk, linux-kernel, loongarch

Quoting Yinbo Zhu (2022-11-28 19:41:55)
> diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
> index 903096bd87f8..4f8f1b8f796d 100644
> --- a/arch/loongarch/Kconfig
> +++ b/arch/loongarch/Kconfig
> @@ -127,6 +127,7 @@ config LOONGARCH
>         select USE_PERCPU_NUMA_NODE_ID
>         select USER_STACKTRACE_SUPPORT
>         select ZONE_DMA32
> +       select COMMON_CLK

Any reason to put this at the end instead of alphabetically?

>  
>  config 32BIT
>         bool
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index d79905f3e174..d13626f63739 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -326,6 +326,15 @@ config COMMON_CLK_LOCHNAGAR
>           This driver supports the clocking features of the Cirrus Logic
>           Lochnagar audio development board.
>  
> +config COMMON_CLK_LOONGSON2
> +       bool "Clock driver for Loongson-2 SoC"
> +       depends on COMMON_CLK && OF
> +       help
> +         This driver provides support for Clock Controller that base on

Don't capitalize 'Clock Controller'

> +         Common Clock Framework Controller (CCF) on Loongson-2 SoC. The

CCF doesn't really matter. Just say "support for clock controller on
Loongson-2 SoC"

> +         Clock Controller can generates and supplies clock to various

Same capitalization comment.

> +         peripherals within the SoC.
> +
>  config COMMON_CLK_NXP
>         def_bool COMMON_CLK && (ARCH_LPC18XX || ARCH_LPC32XX)
>         select REGMAP_MMIO if ARCH_LPC32XX
> diff --git a/drivers/clk/clk-loongson2.c b/drivers/clk/clk-loongson2.c
> new file mode 100644
> index 000000000000..7487effceeab
> --- /dev/null
> +++ b/drivers/clk/clk-loongson2.c
> @@ -0,0 +1,286 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Author: Yinbo Zhu <zhuyinbo@loongson.cn>
> + * Copyright (C) 2022-2023 Loongson Technology Corporation Limited
> + */
> +
> +#include <linux/clkdev.h>

Drop include that isn't used.

> +#include <linux/err.h>
> +#include <linux/init.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <dt-bindings/clock/loongson,ls2k-clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/slab.h>
> +#include <linux/clk.h>
> +
> +#define LOONGSON2_PLL_MULT_SHIFT               32
> +#define LOONGSON2_PLL_MULT_WIDTH               10
> +#define LOONGSON2_PLL_DIV_SHIFT                        26
> +#define LOONGSON2_PLL_DIV_WIDTH                        6
> +#define LOONGSON2_APB_FREQSCALE_SHIFT          20
> +#define LOONGSON2_APB_FREQSCALE_WIDTH          3
> +#define LOONGSON2_USB_FREQSCALE_SHIFT          16
> +#define LOONGSON2_USB_FREQSCALE_WIDTH          3
> +#define LOONGSON2_SATA_FREQSCALE_SHIFT         12
> +#define LOONGSON2_SATA_FREQSCALE_WIDTH         3
> +
> +static void __iomem *loongson2_pll_base;
> +
> +static struct clk_hw *loongson2_clk_register(struct device *dev,
> +                                         const char *name,
> +                                         const char *parent_name,
> +                                         const struct clk_ops *ops,
> +                                         unsigned long flags)
> +{
> +       int ret;
> +       struct clk_hw *hw;
> +       struct clk_init_data init;
> +
> +       /* allocate the divider */
> +       hw = kzalloc(sizeof(*hw), GFP_KERNEL);
> +       if (!hw)
> +               return ERR_PTR(-ENOMEM);
> +
> +       init.name = name;
> +       init.ops = ops;
> +       init.flags = flags;
> +       init.parent_names = (parent_name ? &parent_name : NULL);
> +       init.num_parents = (parent_name ? 1 : 0);
> +       hw->init = &init;
> +
> +       /* register the clock */
> +       ret = clk_hw_register(dev, hw);
> +       if (ret) {
> +               kfree(hw);
> +               hw = ERR_PTR(ret);
> +       }
> +
> +       return hw;
> +}
> +
> +static struct clk_hw *loongson2_clk_pll_register(const char *name,
> +                               const char *parent, void __iomem *reg)
> +{
> +       u64 val;
> +       u32 mult = 1, div = 1;
> +
> +       val = readq((void *)reg);

Drop the cast.

> +
> +       mult = (val >> LOONGSON2_PLL_MULT_SHIFT) &
> +                       clk_div_mask(LOONGSON2_PLL_MULT_WIDTH);
> +       div = (val >> LOONGSON2_PLL_DIV_SHIFT) &
> +                       clk_div_mask(LOONGSON2_PLL_DIV_WIDTH);
> +
> +       return clk_hw_register_fixed_factor(NULL, name, parent,
> +                               CLK_SET_RATE_PARENT, mult, div);
> +}
> +
> +static unsigned long loongson2_apb_recalc_rate(struct clk_hw *hw,
> +                                         unsigned long parent_rate)
> +{
> +       u64 val;
> +       u32 mult;
> +       unsigned long rate;
> +
> +       val = readq((void *)(loongson2_pll_base + 0x50));

Drop the cast.

> +
> +       mult = (val >> LOONGSON2_APB_FREQSCALE_SHIFT) &
> +                       clk_div_mask(LOONGSON2_APB_FREQSCALE_WIDTH);
> +
> +       rate = parent_rate * (mult + 1);
> +       do_div(rate, 8);
> +
> +       return rate;
> +}
> +
> +static const struct clk_ops loongson2_apb_clk_ops = {
> +       .recalc_rate = loongson2_apb_recalc_rate,
> +};
> +
> +static unsigned long loongson2_usb_recalc_rate(struct clk_hw *hw,
> +                                         unsigned long parent_rate)
> +{
> +       u64 val;
> +       u32 mult;
> +       unsigned long rate;
> +
> +       val = readq((void *)(loongson2_pll_base + 0x50));

Drop the cast.

> +
> +       mult = (val >> LOONGSON2_USB_FREQSCALE_SHIFT) &
> +                       clk_div_mask(LOONGSON2_USB_FREQSCALE_WIDTH);
> +
> +       rate = parent_rate * (mult + 1);
> +       do_div(rate, 8);

Why is do_div() being used?

> +
> +       return rate;
> +}
> +
> +static const struct clk_ops loongson2_usb_clk_ops = {
> +       .recalc_rate = loongson2_usb_recalc_rate,
> +};
> +
> +static unsigned long loongson2_sata_recalc_rate(struct clk_hw *hw,
> +                                         unsigned long parent_rate)
> +{
> +       u64 val;
> +       u32 mult;
> +       unsigned long rate;
> +
> +       val = readq((void *)(loongson2_pll_base + 0x50));

Drop the cast.

> +
> +       mult = (val >> LOONGSON2_SATA_FREQSCALE_SHIFT) &
> +                       clk_div_mask(LOONGSON2_SATA_FREQSCALE_WIDTH);
> +
> +       rate = parent_rate * (mult + 1);
> +       do_div(rate, 8);
> +
> +       return rate;
> +}
> +
> +static const struct clk_ops loongson2_sata_clk_ops = {
> +       .recalc_rate = loongson2_sata_recalc_rate,
> +};
> +
> +static void loongson2_check_clk_hws(struct clk_hw *clks[], unsigned int count)

Inline this function.

> +{
> +       unsigned int i;
> +
> +       for (i = 0; i < count; i++)
> +               if (IS_ERR(clks[i]))
> +                       pr_err("Loongson2 clk %u: register failed with %ld\n"
> +                               , i, PTR_ERR(clks[i]));

Put the comma on the line above please.

> +}
> +
> +static struct clk_hw *loongson2_obtain_fixed_clk_hw(
> +                                       struct device_node *np,
> +                                       const char *name)
> +{
> +       struct clk *clk;
> +
> +       clk = of_clk_get_by_name(np, name);
> +       if (IS_ERR(clk))
> +               return ERR_PTR(-ENOENT);
> +
> +       return __clk_get_hw(clk);

Please don't implement this whole function. Instead, use clk_parent_data
and the 'fw_name' or 'index' members to assign clk parents.

> +}
> +
> +static void __init loongson2_clocks_init(struct device_node *np)
> +{
> +       struct clk_hw **hws;
> +       struct clk_hw_onecell_data *clk_hw_data;
> +       spinlock_t loongson2_clk_lock;
> +
> +       loongson2_pll_base = of_iomap(np, 0);
> +
> +       if (!loongson2_pll_base) {
> +               pr_err("clk: unable to map loongson2 clk registers\n");
> +               goto err;

return?

> +       }
> +
> +       clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, LOONGSON2_CLK_END),
> +                                       GFP_KERNEL);
> +       if (WARN_ON(!clk_hw_data))
> +               goto err;
> +
> +       clk_hw_data->num = LOONGSON2_CLK_END;
> +       hws = clk_hw_data->hws;
> +
> +       hws[LOONGSON2_REF_100M] = loongson2_obtain_fixed_clk_hw(np,
> +                                               "ref_100m");
> +
> +       hws[LOONGSON2_NODE_PLL] = loongson2_clk_pll_register("node_pll",
> +                                               "ref_100m",
> +                                               loongson2_pll_base);
> +
> +       hws[LOONGSON2_DDR_PLL] = loongson2_clk_pll_register("ddr_pll",
> +                                               "ref_100m",
> +                                               loongson2_pll_base + 0x10);
> +
> +       hws[LOONGSON2_DC_PLL] = loongson2_clk_pll_register("dc_pll",
> +                                               "ref_100m",
> +                                               loongson2_pll_base + 0x20);
> +
> +       hws[LOONGSON2_PIX0_PLL] = loongson2_clk_pll_register("pix0_pll",
> +                                               "ref_100m",
> +                                               loongson2_pll_base + 0x30);
> +
> +       hws[LOONGSON2_PIX1_PLL] = loongson2_clk_pll_register("pix1_pll",
> +                                               "ref_100m",
> +                                               loongson2_pll_base + 0x40);
> +
> +       hws[LOONGSON2_NODE_CLK] = clk_hw_register_divider(NULL, "node",
> +                                               "node_pll", 0,
> +                                               loongson2_pll_base + 0x8, 0,
> +                                               6, CLK_DIVIDER_ONE_BASED,
> +                                               &loongson2_clk_lock);
> +
> +       /*
> +        * The hda clk divisor in the upper 32bits and the clk-prodiver
> +        * layer code doesn't support 64bit io operation thus a conversion
> +        * is required that subtract shift by 32 and add 4byte to the hda
> +        * address
> +        */
> +       hws[LOONGSON2_HDA_CLK] = clk_hw_register_divider(NULL, "hda",
> +                                               "ddr_pll", 0,
> +                                               loongson2_pll_base + 0x22, 12,
> +                                               7, CLK_DIVIDER_ONE_BASED,
> +                                               &loongson2_clk_lock);
> +
> +       hws[LOONGSON2_GPU_CLK] = clk_hw_register_divider(NULL, "gpu",
> +                                               "ddr_pll", 0,
> +                                               loongson2_pll_base + 0x18, 22,
> +                                               6, CLK_DIVIDER_ONE_BASED,
> +                                               &loongson2_clk_lock);
> +
> +       hws[LOONGSON2_DDR_CLK] = clk_hw_register_divider(NULL, "ddr",
> +                                               "ddr_pll", 0,
> +                                               loongson2_pll_base + 0x18, 0,
> +                                               6, CLK_DIVIDER_ONE_BASED,
> +                                               &loongson2_clk_lock);
> +
> +       hws[LOONGSON2_GMAC_CLK] = clk_hw_register_divider(NULL, "gmac",
> +                                               "dc_pll", 0,
> +                                               loongson2_pll_base + 0x28, 22,
> +                                               6, CLK_DIVIDER_ONE_BASED,
> +                                               &loongson2_clk_lock);
> +
> +       hws[LOONGSON2_DC_CLK] = clk_hw_register_divider(NULL, "dc",
> +                                               "dc_pll", 0,
> +                                               loongson2_pll_base + 0x28, 0,
> +                                               6, CLK_DIVIDER_ONE_BASED,
> +                                               &loongson2_clk_lock);
> +
> +       hws[LOONGSON2_APB_CLK] = loongson2_clk_register(NULL, "apb",
> +                                               "gmac",
> +                                               &loongson2_apb_clk_ops, 0);
> +
> +       hws[LOONGSON2_USB_CLK] = loongson2_clk_register(NULL, "usb",
> +                                               "gmac",
> +                                               &loongson2_usb_clk_ops, 0);
> +
> +       hws[LOONGSON2_SATA_CLK] = loongson2_clk_register(NULL, "sata",
> +                                               "gmac",
> +                                               &loongson2_sata_clk_ops, 0);
> +
> +       hws[LOONGSON2_PIX0_CLK] = clk_hw_register_divider(NULL, "pix0",
> +                                               "pix0_pll", 0,
> +                                               loongson2_pll_base + 0x38, 0, 6,
> +                                               CLK_DIVIDER_ONE_BASED,
> +                                               &loongson2_clk_lock);
> +
> +       hws[LOONGSON2_PIX1_CLK] = clk_hw_register_divider(NULL, "pix1",
> +                                               "pix1_pll", 0,
> +                                               loongson2_pll_base + 0x48, 0, 6,
> +                                               CLK_DIVIDER_ONE_BASED,
> +                                               &loongson2_clk_lock);
> +
> +       loongson2_check_clk_hws(hws, LOONGSON2_CLK_END);
> +
> +       of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
> +
> +err:
> +       iounmap(loongson2_pll_base);
> +}
> +
> +CLK_OF_DECLARE(loongson2_clk, "loongson,ls2k-clk", loongson2_clocks_init);

Any reason this can't be a platform driver?

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

* Re: [PATCH v10 1/4] dt-bindings: clock: add loongson-2 clock include file
  2022-11-29  3:41 [PATCH v10 1/4] dt-bindings: clock: add loongson-2 clock include file Yinbo Zhu
                   ` (2 preceding siblings ...)
  2022-11-29  3:41 ` [PATCH v10 4/4] dt-bindings: clock: add loongson-2 clock Yinbo Zhu
@ 2023-02-10 23:42 ` Stephen Boyd
  3 siblings, 0 replies; 24+ messages in thread
From: Stephen Boyd @ 2023-02-10 23:42 UTC (permalink / raw)
  To: Huacai Chen, Jianmin Lv, Jiaxun Yang, Krzysztof Kozlowski,
	Michael Turquette, Rob Herring, WANG Xuerui, Yang Li, Yinbo Zhu,
	devicetree, linux-clk, linux-kernel, loongarch
  Cc: Krzysztof Kozlowski

Quoting Yinbo Zhu (2022-11-28 19:41:54)
> This file defines all Loongson-2 SoC clock indexes, it should be
> included in the device tree in which there's device using the
> clocks.
> 
> Signed-off-by: Yinbo Zhu <zhuyinbo@loongson.cn>
> Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> ---

Applied to clk-next

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

* Re: [PATCH v10 4/4] dt-bindings: clock: add loongson-2 clock
  2022-11-29  3:41 ` [PATCH v10 4/4] dt-bindings: clock: add loongson-2 clock Yinbo Zhu
@ 2023-02-10 23:43   ` Stephen Boyd
  0 siblings, 0 replies; 24+ messages in thread
From: Stephen Boyd @ 2023-02-10 23:43 UTC (permalink / raw)
  To: Huacai Chen, Jianmin Lv, Jiaxun Yang, Krzysztof Kozlowski,
	Michael Turquette, Rob Herring, WANG Xuerui, Yang Li, Yinbo Zhu,
	devicetree, linux-clk, linux-kernel, loongarch
  Cc: Krzysztof Kozlowski

Quoting Yinbo Zhu (2022-11-28 19:41:57)
> Add the Loongson-2 clock binding with DT schema format using
> json-schema.
> 
> Signed-off-by: Yinbo Zhu <zhuyinbo@loongson.cn>
> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> ---

Applied to clk-next

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

* Re: [PATCH v10 2/4] clk: clk-loongson2: add clock controller driver support
  2023-02-10 23:42   ` Stephen Boyd
@ 2023-02-15  7:35     ` zhuyinbo
  2023-02-17 22:15       ` Stephen Boyd
  0 siblings, 1 reply; 24+ messages in thread
From: zhuyinbo @ 2023-02-15  7:35 UTC (permalink / raw)
  To: Stephen Boyd, Huacai Chen, Jianmin Lv, Jiaxun Yang,
	Krzysztof Kozlowski, Michael Turquette, Rob Herring, WANG Xuerui,
	Yang Li, devicetree, linux-clk, linux-kernel, loongarch,
	wanghongliang, liupeibao, zhuyinbo


在 2023/2/11 上午7:42, Stephen Boyd 写道:
> Quoting Yinbo Zhu (2022-11-28 19:41:55)
>> diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
>> index 903096bd87f8..4f8f1b8f796d 100644
>> --- a/arch/loongarch/Kconfig
>> +++ b/arch/loongarch/Kconfig
>> @@ -127,6 +127,7 @@ config LOONGARCH
>>          select USE_PERCPU_NUMA_NODE_ID
>>          select USER_STACKTRACE_SUPPORT
>>          select ZONE_DMA32
>> +       select COMMON_CLK
> Any reason to put this at the end instead of alphabetically?
okay, I will change it as alphabetically.
>>   
>>   config 32BIT
>>          bool
>> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
>> index d79905f3e174..d13626f63739 100644
>> --- a/drivers/clk/Kconfig
>> +++ b/drivers/clk/Kconfig
>> @@ -326,6 +326,15 @@ config COMMON_CLK_LOCHNAGAR
>>            This driver supports the clocking features of the Cirrus Logic
>>            Lochnagar audio development board.
>>   
>> +config COMMON_CLK_LOONGSON2
>> +       bool "Clock driver for Loongson-2 SoC"
>> +       depends on COMMON_CLK && OF
>> +       help
>> +         This driver provides support for Clock Controller that base on
> Don't capitalize 'Clock Controller'
okay, I got it.
>
>> +         Common Clock Framework Controller (CCF) on Loongson-2 SoC. The
> CCF doesn't really matter. Just say "support for clock controller on
> Loongson-2 SoC"
okay, I got it.
>
>> +         Clock Controller can generates and supplies clock to various
> Same capitalization comment.
okay, I got it.
>
>> +         peripherals within the SoC.
>> +
>>   config COMMON_CLK_NXP
>>          def_bool COMMON_CLK && (ARCH_LPC18XX || ARCH_LPC32XX)
>>          select REGMAP_MMIO if ARCH_LPC32XX
>> diff --git a/drivers/clk/clk-loongson2.c b/drivers/clk/clk-loongson2.c
>> new file mode 100644
>> index 000000000000..7487effceeab
>> --- /dev/null
>> +++ b/drivers/clk/clk-loongson2.c
>> @@ -0,0 +1,286 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * Author: Yinbo Zhu <zhuyinbo@loongson.cn>
>> + * Copyright (C) 2022-2023 Loongson Technology Corporation Limited
>> + */
>> +
>> +#include <linux/clkdev.h>
> Drop include that isn't used.
okay, I got it.
>
>> +#include <linux/err.h>
>> +#include <linux/init.h>
>> +#include <linux/of.h>
>> +#include <linux/of_address.h>
>> +#include <dt-bindings/clock/loongson,ls2k-clk.h>
>> +#include <linux/clk-provider.h>
>> +#include <linux/slab.h>
>> +#include <linux/clk.h>
>> +
>> +#define LOONGSON2_PLL_MULT_SHIFT               32
>> +#define LOONGSON2_PLL_MULT_WIDTH               10
>> +#define LOONGSON2_PLL_DIV_SHIFT                        26
>> +#define LOONGSON2_PLL_DIV_WIDTH                        6
>> +#define LOONGSON2_APB_FREQSCALE_SHIFT          20
>> +#define LOONGSON2_APB_FREQSCALE_WIDTH          3
>> +#define LOONGSON2_USB_FREQSCALE_SHIFT          16
>> +#define LOONGSON2_USB_FREQSCALE_WIDTH          3
>> +#define LOONGSON2_SATA_FREQSCALE_SHIFT         12
>> +#define LOONGSON2_SATA_FREQSCALE_WIDTH         3
>> +
>> +static void __iomem *loongson2_pll_base;
>> +
>> +static struct clk_hw *loongson2_clk_register(struct device *dev,
>> +                                         const char *name,
>> +                                         const char *parent_name,
>> +                                         const struct clk_ops *ops,
>> +                                         unsigned long flags)
>> +{
>> +       int ret;
>> +       struct clk_hw *hw;
>> +       struct clk_init_data init;
>> +
>> +       /* allocate the divider */
>> +       hw = kzalloc(sizeof(*hw), GFP_KERNEL);
>> +       if (!hw)
>> +               return ERR_PTR(-ENOMEM);
>> +
>> +       init.name = name;
>> +       init.ops = ops;
>> +       init.flags = flags;
>> +       init.parent_names = (parent_name ? &parent_name : NULL);
>> +       init.num_parents = (parent_name ? 1 : 0);
>> +       hw->init = &init;
>> +
>> +       /* register the clock */
>> +       ret = clk_hw_register(dev, hw);
>> +       if (ret) {
>> +               kfree(hw);
>> +               hw = ERR_PTR(ret);
>> +       }
>> +
>> +       return hw;
>> +}
>> +
>> +static struct clk_hw *loongson2_clk_pll_register(const char *name,
>> +                               const char *parent, void __iomem *reg)
>> +{
>> +       u64 val;
>> +       u32 mult = 1, div = 1;
>> +
>> +       val = readq((void *)reg);
> Drop the cast.
I will remove the (void *).
>
>> +
>> +       mult = (val >> LOONGSON2_PLL_MULT_SHIFT) &
>> +                       clk_div_mask(LOONGSON2_PLL_MULT_WIDTH);
>> +       div = (val >> LOONGSON2_PLL_DIV_SHIFT) &
>> +                       clk_div_mask(LOONGSON2_PLL_DIV_WIDTH);
>> +
>> +       return clk_hw_register_fixed_factor(NULL, name, parent,
>> +                               CLK_SET_RATE_PARENT, mult, div);
>> +}
>> +
>> +static unsigned long loongson2_apb_recalc_rate(struct clk_hw *hw,
>> +                                         unsigned long parent_rate)
>> +{
>> +       u64 val;
>> +       u32 mult;
>> +       unsigned long rate;
>> +
>> +       val = readq((void *)(loongson2_pll_base + 0x50));
> Drop the cast.
I will remove the (void *).
>
>> +
>> +       mult = (val >> LOONGSON2_APB_FREQSCALE_SHIFT) &
>> +                       clk_div_mask(LOONGSON2_APB_FREQSCALE_WIDTH);
>> +
>> +       rate = parent_rate * (mult + 1);
>> +       do_div(rate, 8);
>> +
>> +       return rate;
>> +}
>> +
>> +static const struct clk_ops loongson2_apb_clk_ops = {
>> +       .recalc_rate = loongson2_apb_recalc_rate,
>> +};
>> +
>> +static unsigned long loongson2_usb_recalc_rate(struct clk_hw *hw,
>> +                                         unsigned long parent_rate)
>> +{
>> +       u64 val;
>> +       u32 mult;
>> +       unsigned long rate;
>> +
>> +       val = readq((void *)(loongson2_pll_base + 0x50));
> Drop the cast.
I will remove the (void *).
>
>> +
>> +       mult = (val >> LOONGSON2_USB_FREQSCALE_SHIFT) &
>> +                       clk_div_mask(LOONGSON2_USB_FREQSCALE_WIDTH);
>> +
>> +       rate = parent_rate * (mult + 1);
>> +       do_div(rate, 8);
> Why is do_div() being used?
no expecial reason, I only want to get a result that rate divide 8.
>
>> +
>> +       return rate;
>> +}
>> +
>> +static const struct clk_ops loongson2_usb_clk_ops = {
>> +       .recalc_rate = loongson2_usb_recalc_rate,
>> +};
>> +
>> +static unsigned long loongson2_sata_recalc_rate(struct clk_hw *hw,
>> +                                         unsigned long parent_rate)
>> +{
>> +       u64 val;
>> +       u32 mult;
>> +       unsigned long rate;
>> +
>> +       val = readq((void *)(loongson2_pll_base + 0x50));
> Drop the cast.
I will remove the (void *).
>
>> +
>> +       mult = (val >> LOONGSON2_SATA_FREQSCALE_SHIFT) &
>> +                       clk_div_mask(LOONGSON2_SATA_FREQSCALE_WIDTH);
>> +
>> +       rate = parent_rate * (mult + 1);
>> +       do_div(rate, 8);
>> +
>> +       return rate;
>> +}
>> +
>> +static const struct clk_ops loongson2_sata_clk_ops = {
>> +       .recalc_rate = loongson2_sata_recalc_rate,
>> +};
>> +
>> +static void loongson2_check_clk_hws(struct clk_hw *clks[], unsigned int count)
> Inline this function.
I will add it.
>
>> +{
>> +       unsigned int i;
>> +
>> +       for (i = 0; i < count; i++)
>> +               if (IS_ERR(clks[i]))
>> +                       pr_err("Loongson2 clk %u: register failed with %ld\n"
>> +                               , i, PTR_ERR(clks[i]));
> Put the comma on the line above please.
okay, I got it.
>
>> +}
>> +
>> +static struct clk_hw *loongson2_obtain_fixed_clk_hw(
>> +                                       struct device_node *np,
>> +                                       const char *name)
>> +{
>> +       struct clk *clk;
>> +
>> +       clk = of_clk_get_by_name(np, name);
>> +       if (IS_ERR(clk))
>> +               return ERR_PTR(-ENOENT);
>> +
>> +       return __clk_get_hw(clk);
> Please don't implement this whole function. Instead, use clk_parent_data
> and the 'fw_name' or 'index' members to assign clk parents.

at present,  the child clk doesn't depend on the clk_parent_data,   eg.

hws[LOONGSON2_NODE_PLL] = loongson2_clk_pll_register("node_pll", 
"ref_100m", loongson2_pll_base);

static struct clk_hw *loongson2_clk_pll_register(const char *name,
                                 const char *parent, void __iomem *reg)
{
         u64 val;
         u32 mult = 1, div = 1;

         val = readq((void *)reg);

         mult = (val >> LOONGSON2_PLL_MULT_SHIFT) &
                         clk_div_mask(LOONGSON2_PLL_MULT_WIDTH);
         div = (val >> LOONGSON2_PLL_DIV_SHIFT) &
                         clk_div_mask(LOONGSON2_PLL_DIV_WIDTH);

         return clk_hw_register_fixed_factor(NULL, name, parent,
                                 CLK_SET_RATE_PARENT, mult, div);
}

you meaning is to use clk_parent_data to rework 
loongson2_clk_pll_register  and drop

loongson2_obtain_fixed_clk_hw ?

>
>> +}
>> +
>> +static void __init loongson2_clocks_init(struct device_node *np)
>> +{
>> +       struct clk_hw **hws;
>> +       struct clk_hw_onecell_data *clk_hw_data;
>> +       spinlock_t loongson2_clk_lock;
>> +
>> +       loongson2_pll_base = of_iomap(np, 0);
>> +
>> +       if (!loongson2_pll_base) {
>> +               pr_err("clk: unable to map loongson2 clk registers\n");
>> +               goto err;
> return?
sorry, I don't get it.  you meaning is that  remove "goto err". Instead, 
add a "return".
>
>> +       }
>> +
>> +       clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, LOONGSON2_CLK_END),
>> +                                       GFP_KERNEL);
>> +       if (WARN_ON(!clk_hw_data))
>> +               goto err;
>> +
>> +       clk_hw_data->num = LOONGSON2_CLK_END;
>> +       hws = clk_hw_data->hws;
>> +
>> +       hws[LOONGSON2_REF_100M] = loongson2_obtain_fixed_clk_hw(np,
>> +                                               "ref_100m");
>> +
>> +       hws[LOONGSON2_NODE_PLL] = loongson2_clk_pll_register("node_pll",
>> +                                               "ref_100m",
>> +                                               loongson2_pll_base);
>> +
>> +       hws[LOONGSON2_DDR_PLL] = loongson2_clk_pll_register("ddr_pll",
>> +                                               "ref_100m",
>> +                                               loongson2_pll_base + 0x10);
>> +
>> +       hws[LOONGSON2_DC_PLL] = loongson2_clk_pll_register("dc_pll",
>> +                                               "ref_100m",
>> +                                               loongson2_pll_base + 0x20);
>> +
>> +       hws[LOONGSON2_PIX0_PLL] = loongson2_clk_pll_register("pix0_pll",
>> +                                               "ref_100m",
>> +                                               loongson2_pll_base + 0x30);
>> +
>> +       hws[LOONGSON2_PIX1_PLL] = loongson2_clk_pll_register("pix1_pll",
>> +                                               "ref_100m",
>> +                                               loongson2_pll_base + 0x40);
>> +
>> +       hws[LOONGSON2_NODE_CLK] = clk_hw_register_divider(NULL, "node",
>> +                                               "node_pll", 0,
>> +                                               loongson2_pll_base + 0x8, 0,
>> +                                               6, CLK_DIVIDER_ONE_BASED,
>> +                                               &loongson2_clk_lock);
>> +
>> +       /*
>> +        * The hda clk divisor in the upper 32bits and the clk-prodiver
>> +        * layer code doesn't support 64bit io operation thus a conversion
>> +        * is required that subtract shift by 32 and add 4byte to the hda
>> +        * address
>> +        */
>> +       hws[LOONGSON2_HDA_CLK] = clk_hw_register_divider(NULL, "hda",
>> +                                               "ddr_pll", 0,
>> +                                               loongson2_pll_base + 0x22, 12,
>> +                                               7, CLK_DIVIDER_ONE_BASED,
>> +                                               &loongson2_clk_lock);
>> +
>> +       hws[LOONGSON2_GPU_CLK] = clk_hw_register_divider(NULL, "gpu",
>> +                                               "ddr_pll", 0,
>> +                                               loongson2_pll_base + 0x18, 22,
>> +                                               6, CLK_DIVIDER_ONE_BASED,
>> +                                               &loongson2_clk_lock);
>> +
>> +       hws[LOONGSON2_DDR_CLK] = clk_hw_register_divider(NULL, "ddr",
>> +                                               "ddr_pll", 0,
>> +                                               loongson2_pll_base + 0x18, 0,
>> +                                               6, CLK_DIVIDER_ONE_BASED,
>> +                                               &loongson2_clk_lock);
>> +
>> +       hws[LOONGSON2_GMAC_CLK] = clk_hw_register_divider(NULL, "gmac",
>> +                                               "dc_pll", 0,
>> +                                               loongson2_pll_base + 0x28, 22,
>> +                                               6, CLK_DIVIDER_ONE_BASED,
>> +                                               &loongson2_clk_lock);
>> +
>> +       hws[LOONGSON2_DC_CLK] = clk_hw_register_divider(NULL, "dc",
>> +                                               "dc_pll", 0,
>> +                                               loongson2_pll_base + 0x28, 0,
>> +                                               6, CLK_DIVIDER_ONE_BASED,
>> +                                               &loongson2_clk_lock);
>> +
>> +       hws[LOONGSON2_APB_CLK] = loongson2_clk_register(NULL, "apb",
>> +                                               "gmac",
>> +                                               &loongson2_apb_clk_ops, 0);
>> +
>> +       hws[LOONGSON2_USB_CLK] = loongson2_clk_register(NULL, "usb",
>> +                                               "gmac",
>> +                                               &loongson2_usb_clk_ops, 0);
>> +
>> +       hws[LOONGSON2_SATA_CLK] = loongson2_clk_register(NULL, "sata",
>> +                                               "gmac",
>> +                                               &loongson2_sata_clk_ops, 0);
>> +
>> +       hws[LOONGSON2_PIX0_CLK] = clk_hw_register_divider(NULL, "pix0",
>> +                                               "pix0_pll", 0,
>> +                                               loongson2_pll_base + 0x38, 0, 6,
>> +                                               CLK_DIVIDER_ONE_BASED,
>> +                                               &loongson2_clk_lock);
>> +
>> +       hws[LOONGSON2_PIX1_CLK] = clk_hw_register_divider(NULL, "pix1",
>> +                                               "pix1_pll", 0,
>> +                                               loongson2_pll_base + 0x48, 0, 6,
>> +                                               CLK_DIVIDER_ONE_BASED,
>> +                                               &loongson2_clk_lock);
>> +
>> +       loongson2_check_clk_hws(hws, LOONGSON2_CLK_END);
>> +
>> +       of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
>> +
>> +err:
>> +       iounmap(loongson2_pll_base);
>> +}
>> +
>> +CLK_OF_DECLARE(loongson2_clk, "loongson,ls2k-clk", loongson2_clocks_init);
> Any reason this can't be a platform driver?

For the compatible consideration of other clock controllers of 
Loongson-2 series in the future, the way of using dts can be

better compatible.


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

* Re: [PATCH v10 2/4] clk: clk-loongson2: add clock controller driver support
  2023-02-15  7:35     ` zhuyinbo
@ 2023-02-17 22:15       ` Stephen Boyd
  2023-02-20  5:44         ` zhuyinbo
  0 siblings, 1 reply; 24+ messages in thread
From: Stephen Boyd @ 2023-02-17 22:15 UTC (permalink / raw)
  To: Huacai Chen, Jianmin Lv, Jiaxun Yang, Krzysztof Kozlowski,
	Michael Turquette, Rob Herring, WANG Xuerui, Yang Li, devicetree,
	linux-clk, linux-kernel, liupeibao, loongarch, wanghongliang,
	zhuyinbo

Quoting zhuyinbo (2023-02-14 23:35:22)
> 
> 在 2023/2/11 上午7:42, Stephen Boyd 写道:
> > Quoting Yinbo Zhu (2022-11-28 19:41:55)
> >
> >> +
> >> +       mult = (val >> LOONGSON2_USB_FREQSCALE_SHIFT) &
> >> +                       clk_div_mask(LOONGSON2_USB_FREQSCALE_WIDTH);
> >> +
> >> +       rate = parent_rate * (mult + 1);
> >> +       do_div(rate, 8);
> > Why is do_div() being used?
> no expecial reason, I only want to get a result that rate divide 8.

Ok, you can use div_u64() here and simplify.

> >
> 
> you meaning is to use clk_parent_data to rework 
> loongson2_clk_pll_register  and drop
> 
> loongson2_obtain_fixed_clk_hw ?

Yes

> 
> >
> >> +}
> >> +
> >> +static void __init loongson2_clocks_init(struct device_node *np)
> >> +{
> >> +       struct clk_hw **hws;
> >> +       struct clk_hw_onecell_data *clk_hw_data;
> >> +       spinlock_t loongson2_clk_lock;
> >> +
> >> +       loongson2_pll_base = of_iomap(np, 0);
> >> +
> >> +       if (!loongson2_pll_base) {
> >> +               pr_err("clk: unable to map loongson2 clk registers\n");
> >> +               goto err;
> > return?
> sorry, I don't get it.  you meaning is that  remove "goto err". Instead, 
> add a "return".

Yes.

> >
> >> +       }
> >> +
> >> +       clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, LOONGSON2_CLK_END),
> >> +                                       GFP_KERNEL);
> >> +       if (WARN_ON(!clk_hw_data))
> >> +               goto err;
[...]
> >> +
> >> +err:
> >> +       iounmap(loongson2_pll_base);
> >> +}
> >> +
> >> +CLK_OF_DECLARE(loongson2_clk, "loongson,ls2k-clk", loongson2_clocks_init);
> > Any reason this can't be a platform driver?
> 
> For the compatible consideration of other clock controllers of 
> Loongson-2 series in the future, the way of using dts can be
> 
> better compatible.
> 

Sorry that sentence doesn't make sense to me. The use of dts doesn't
require the use of CLK_OF_DECLARE.

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

* Re: [PATCH v10 2/4] clk: clk-loongson2: add clock controller driver support
  2023-02-17 22:15       ` Stephen Boyd
@ 2023-02-20  5:44         ` zhuyinbo
  2023-02-21 23:07           ` Stephen Boyd
  0 siblings, 1 reply; 24+ messages in thread
From: zhuyinbo @ 2023-02-20  5:44 UTC (permalink / raw)
  To: Stephen Boyd, Huacai Chen, Jianmin Lv, Jiaxun Yang,
	Krzysztof Kozlowski, Michael Turquette, Rob Herring, WANG Xuerui,
	Yang Li, devicetree, linux-clk, linux-kernel, liupeibao,
	loongarch, wanghongliang


在 2023/2/18 上午6:15, Stephen Boyd 写道:
> Quoting zhuyinbo (2023-02-14 23:35:22)
>> 在 2023/2/11 上午7:42, Stephen Boyd 写道:
>>> Quoting Yinbo Zhu (2022-11-28 19:41:55)
>>>
>>>> +
>>>> +       mult = (val >> LOONGSON2_USB_FREQSCALE_SHIFT) &
>>>> +                       clk_div_mask(LOONGSON2_USB_FREQSCALE_WIDTH);
>>>> +
>>>> +       rate = parent_rate * (mult + 1);
>>>> +       do_div(rate, 8);
>>> Why is do_div() being used?
>> no expecial reason, I only want to get a result that rate divide 8.
> Ok, you can use div_u64() here and simplify.
okay, I got it.
>
>> you meaning is to use clk_parent_data to rework
>> loongson2_clk_pll_register  and drop
>>
>> loongson2_obtain_fixed_clk_hw ?
> Yes
>
>>>> +}
>>>> +
>>>> +static void __init loongson2_clocks_init(struct device_node *np)
>>>> +{
>>>> +       struct clk_hw **hws;
>>>> +       struct clk_hw_onecell_data *clk_hw_data;
>>>> +       spinlock_t loongson2_clk_lock;
>>>> +
>>>> +       loongson2_pll_base = of_iomap(np, 0);
>>>> +
>>>> +       if (!loongson2_pll_base) {
>>>> +               pr_err("clk: unable to map loongson2 clk registers\n");
>>>> +               goto err;
>>> return?
>> sorry, I don't get it.  you meaning is that  remove "goto err". Instead,
>> add a "return".
> Yes.
>
>>>> +       }
>>>> +
>>>> +       clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, LOONGSON2_CLK_END),
>>>> +                                       GFP_KERNEL);
>>>> +       if (WARN_ON(!clk_hw_data))
>>>> +               goto err;
> [...]
>>>> +
>>>> +err:
>>>> +       iounmap(loongson2_pll_base);
>>>> +}
>>>> +
>>>> +CLK_OF_DECLARE(loongson2_clk, "loongson,ls2k-clk", loongson2_clocks_init);
>>> Any reason this can't be a platform driver?

Your question is that  why I don't use the platform_driver_register to 
register  clk and use CLK_OF_DECLARE ?

I was  consider other clock controllers of Loongson-2 series may be 
different with 2k1000 and I can add a line

CLK_OF_DECLARE() for compatible other platform in the future. eg.

CLK_OF_DECLARE(loongson2_clk, "loongson,ls2k-clk", loongson2_clocks_init);

+  CLK_OF_DECLARE(xxx1, xxx2,  xxx3);  // for other clock controllers of 
Loongson-2 series

>> For the compatible consideration of other clock controllers of
>> Loongson-2 series in the future, the way of using dts can be
>>
>> better compatible.
>>
> Sorry that sentence doesn't make sense to me. The use of dts doesn't
> require the use of CLK_OF_DECLARE.

yes, the use of dts doesn't require the use of CLK_OF_DECLARE and can 
use platform_driver_register

but my drvier not use platform_driver_register to register  clk and use 
CLK_OF_DECLARE to match of_clk_init.


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

* Re: [PATCH v10 2/4] clk: clk-loongson2: add clock controller driver support
  2023-02-20  5:44         ` zhuyinbo
@ 2023-02-21 23:07           ` Stephen Boyd
  2023-02-22  2:02             ` zhuyinbo
  0 siblings, 1 reply; 24+ messages in thread
From: Stephen Boyd @ 2023-02-21 23:07 UTC (permalink / raw)
  To: Huacai Chen, Jianmin Lv, Jiaxun Yang, Krzysztof Kozlowski,
	Michael Turquette, Rob Herring, WANG Xuerui, Yang Li, devicetree,
	linux-clk, linux-kernel, liupeibao, loongarch, wanghongliang,
	zhuyinbo

Quoting zhuyinbo (2023-02-19 21:44:51)
> 
> 在 2023/2/18 上午6:15, Stephen Boyd 写道:
> > Quoting zhuyinbo (2023-02-14 23:35:22)
> >> 在 2023/2/11 上午7:42, Stephen Boyd 写道:
> >>>> +
> >>>> +err:
> >>>> +       iounmap(loongson2_pll_base);
> >>>> +}
> >>>> +
> >>>> +CLK_OF_DECLARE(loongson2_clk, "loongson,ls2k-clk", loongson2_clocks_init);
> >>> Any reason this can't be a platform driver?
> 
> Your question is that  why I don't use the platform_driver_register to 
> register  clk and use CLK_OF_DECLARE ?

Yes.

> 
> I was  consider other clock controllers of Loongson-2 series may be 
> different with 2k1000 and I can add a line
> 
> CLK_OF_DECLARE() for compatible other platform in the future. eg.
> 
> CLK_OF_DECLARE(loongson2_clk, "loongson,ls2k-clk", loongson2_clocks_init);
> 
> +  CLK_OF_DECLARE(xxx1, xxx2,  xxx3);  // for other clock controllers of 
> Loongson-2 series
> 
> >> For the compatible consideration of other clock controllers of
> >> Loongson-2 series in the future, the way of using dts can be
> >>
> >> better compatible.
> >>
> > Sorry that sentence doesn't make sense to me. The use of dts doesn't
> > require the use of CLK_OF_DECLARE.
> 
> yes, the use of dts doesn't require the use of CLK_OF_DECLARE and can 
> use platform_driver_register
> 
> but my drvier not use platform_driver_register to register  clk and use 
> CLK_OF_DECLARE to match of_clk_init.

of_clk_init() is there to register clks that are needed for early init,
i.e. the clockevent/clocksource or the root interrupt controller
(irqchip). Otherwise, it isn't necessary to register clks via
of_clk_init().

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

* Re: [PATCH v10 2/4] clk: clk-loongson2: add clock controller driver support
  2023-02-21 23:07           ` Stephen Boyd
@ 2023-02-22  2:02             ` zhuyinbo
  2023-02-22  5:10               ` zhuyinbo
  0 siblings, 1 reply; 24+ messages in thread
From: zhuyinbo @ 2023-02-22  2:02 UTC (permalink / raw)
  To: Stephen Boyd, Huacai Chen, Jianmin Lv, Jiaxun Yang,
	Krzysztof Kozlowski, Michael Turquette, Rob Herring, WANG Xuerui,
	Yang Li, devicetree, linux-clk, linux-kernel, liupeibao,
	loongarch, wanghongliang


在 2023/2/22 上午7:07, Stephen Boyd 写道:
> Quoting zhuyinbo (2023-02-19 21:44:51)
>> 在 2023/2/18 上午6:15, Stephen Boyd 写道:
>>> Quoting zhuyinbo (2023-02-14 23:35:22)
>>>> 在 2023/2/11 上午7:42, Stephen Boyd 写道:
>>>>>> +
>>>>>> +err:
>>>>>> +       iounmap(loongson2_pll_base);
>>>>>> +}
>>>>>> +
>>>>>> +CLK_OF_DECLARE(loongson2_clk, "loongson,ls2k-clk", loongson2_clocks_init);
>>>>> Any reason this can't be a platform driver?
>> Your question is that  why I don't use the platform_driver_register to
>> register  clk and use CLK_OF_DECLARE ?
> Yes.
>
>> I was  consider other clock controllers of Loongson-2 series may be
>> different with 2k1000 and I can add a line
>>
>> CLK_OF_DECLARE() for compatible other platform in the future. eg.
>>
>> CLK_OF_DECLARE(loongson2_clk, "loongson,ls2k-clk", loongson2_clocks_init);
>>
>> +  CLK_OF_DECLARE(xxx1, xxx2,  xxx3);  // for other clock controllers of
>> Loongson-2 series
>>
>>>> For the compatible consideration of other clock controllers of
>>>> Loongson-2 series in the future, the way of using dts can be
>>>>
>>>> better compatible.
>>>>
>>> Sorry that sentence doesn't make sense to me. The use of dts doesn't
>>> require the use of CLK_OF_DECLARE.
>> yes, the use of dts doesn't require the use of CLK_OF_DECLARE and can
>> use platform_driver_register
>>
>> but my drvier not use platform_driver_register to register  clk and use
>> CLK_OF_DECLARE to match of_clk_init.
> of_clk_init() is there to register clks that are needed for early init,
> i.e. the clockevent/clocksource or the root interrupt controller
> (irqchip). Otherwise, it isn't necessary to register clks via
> of_clk_init().
okay, I got it.


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

* Re: [PATCH v10 2/4] clk: clk-loongson2: add clock controller driver support
  2023-02-22  2:02             ` zhuyinbo
@ 2023-02-22  5:10               ` zhuyinbo
  2023-02-22 21:00                 ` Stephen Boyd
  0 siblings, 1 reply; 24+ messages in thread
From: zhuyinbo @ 2023-02-22  5:10 UTC (permalink / raw)
  To: Stephen Boyd, Huacai Chen, Jianmin Lv, Jiaxun Yang,
	Krzysztof Kozlowski, Michael Turquette, Rob Herring, WANG Xuerui,
	Yang Li, devicetree, linux-clk, linux-kernel, liupeibao,
	loongarch, wanghongliang


在 2023/2/22 上午10:02, zhuyinbo 写道:
>
> 在 2023/2/22 上午7:07, Stephen Boyd 写道:
>> Quoting zhuyinbo (2023-02-19 21:44:51)
>>> 在 2023/2/18 上午6:15, Stephen Boyd 写道:
>>>> Quoting zhuyinbo (2023-02-14 23:35:22)
>>>>> 在 2023/2/11 上午7:42, Stephen Boyd 写道:
>>>>>>> +
>>>>>>> +err:
>>>>>>> +       iounmap(loongson2_pll_base);
>>>>>>> +}
>>>>>>> +
>>>>>>> +CLK_OF_DECLARE(loongson2_clk, "loongson,ls2k-clk", 
>>>>>>> loongson2_clocks_init);
>>>>>> Any reason this can't be a platform driver?
>>> Your question is that  why I don't use the platform_driver_register to
>>> register  clk and use CLK_OF_DECLARE ?
>> Yes.
>>
>>> I was  consider other clock controllers of Loongson-2 series may be
>>> different with 2k1000 and I can add a line
>>>
>>> CLK_OF_DECLARE() for compatible other platform in the future. eg.
>>>
>>> CLK_OF_DECLARE(loongson2_clk, "loongson,ls2k-clk", 
>>> loongson2_clocks_init);
>>>
>>> +  CLK_OF_DECLARE(xxx1, xxx2,  xxx3);  // for other clock 
>>> controllers of
>>> Loongson-2 series
>>>
>>>>> For the compatible consideration of other clock controllers of
>>>>> Loongson-2 series in the future, the way of using dts can be
>>>>>
>>>>> better compatible.
>>>>>
>>>> Sorry that sentence doesn't make sense to me. The use of dts doesn't
>>>> require the use of CLK_OF_DECLARE.
>>> yes, the use of dts doesn't require the use of CLK_OF_DECLARE and can
>>> use platform_driver_register
>>>
>>> but my drvier not use platform_driver_register to register clk and use
>>> CLK_OF_DECLARE to match of_clk_init.
>> of_clk_init() is there to register clks that are needed for early init,
>> i.e. the clockevent/clocksource or the root interrupt controller
>> (irqchip). Otherwise, it isn't necessary to register clks via
>> of_clk_init().
> okay, I got it.

and,  the time driver  get clock by CCF that ask loongson2 clock driver 
use CLK_OF_DECLARE

to match of_clk_init.   because  the timer_probe  is very early and the 
timer driver was use TIMER_OF_DECLARE

to match time_probe.


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

* Re: [PATCH v10 2/4] clk: clk-loongson2: add clock controller driver support
  2023-02-22  5:10               ` zhuyinbo
@ 2023-02-22 21:00                 ` Stephen Boyd
  2023-02-23  2:16                   ` zhuyinbo
  0 siblings, 1 reply; 24+ messages in thread
From: Stephen Boyd @ 2023-02-22 21:00 UTC (permalink / raw)
  To: Huacai Chen, Jianmin Lv, Jiaxun Yang, Krzysztof Kozlowski,
	Michael Turquette, Rob Herring, WANG Xuerui, Yang Li, devicetree,
	linux-clk, linux-kernel, liupeibao, loongarch, wanghongliang,
	zhuyinbo

Quoting zhuyinbo (2023-02-21 21:10:14)
> 
> >
> >>> yes, the use of dts doesn't require the use of CLK_OF_DECLARE and can
> >>> use platform_driver_register
> >>>
> >>> but my drvier not use platform_driver_register to register clk and use
> >>> CLK_OF_DECLARE to match of_clk_init.
> >> of_clk_init() is there to register clks that are needed for early init,
> >> i.e. the clockevent/clocksource or the root interrupt controller
> >> (irqchip). Otherwise, it isn't necessary to register clks via
> >> of_clk_init().
> > okay, I got it.
> 
> and,  the time driver  get clock by CCF that ask loongson2 clock driver 
> use CLK_OF_DECLARE
> 
> to match of_clk_init.   because  the timer_probe  is very early and the 
> timer driver was use TIMER_OF_DECLARE
> 
> to match time_probe.
> 

If you have a time driver that gets clks, register those early with
CLK_OF_DECLARE_DRIVER() and then have a platform driver for the rest of
the clk tree that registers clks later.

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

* Re: [PATCH v10 2/4] clk: clk-loongson2: add clock controller driver support
  2023-02-22 21:00                 ` Stephen Boyd
@ 2023-02-23  2:16                   ` zhuyinbo
  2023-02-24 19:10                     ` Stephen Boyd
  0 siblings, 1 reply; 24+ messages in thread
From: zhuyinbo @ 2023-02-23  2:16 UTC (permalink / raw)
  To: Stephen Boyd, Huacai Chen, Jianmin Lv, Jiaxun Yang,
	Krzysztof Kozlowski, Michael Turquette, Rob Herring, WANG Xuerui,
	Yang Li, devicetree, linux-clk, linux-kernel, liupeibao,
	loongarch, wanghongliang


在 2023/2/23 上午5:00, Stephen Boyd 写道:
> Quoting zhuyinbo (2023-02-21 21:10:14)
>>>>> yes, the use of dts doesn't require the use of CLK_OF_DECLARE and can
>>>>> use platform_driver_register
>>>>>
>>>>> but my drvier not use platform_driver_register to register clk and use
>>>>> CLK_OF_DECLARE to match of_clk_init.
>>>> of_clk_init() is there to register clks that are needed for early init,
>>>> i.e. the clockevent/clocksource or the root interrupt controller
>>>> (irqchip). Otherwise, it isn't necessary to register clks via
>>>> of_clk_init().
>>> okay, I got it.
>> and,  the time driver  get clock by CCF that ask loongson2 clock driver
>> use CLK_OF_DECLARE
>>
>> to match of_clk_init.   because  the timer_probe  is very early and the
>> timer driver was use TIMER_OF_DECLARE
>>
>> to match time_probe.
>>
> If you have a time driver that gets clks, register those early with
> CLK_OF_DECLARE_DRIVER() and then have a platform driver for the rest of
> the clk tree that registers clks later.

okay, I got it.  and this series patch I will use platform driver. 
later, if the loongson2 time driver use the

CLK_OF_DECLARE style I will make a alone time clk driver for it that 
use  CLK_OF_DECLARE_DRIVER()


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

* Re: [PATCH v10 2/4] clk: clk-loongson2: add clock controller driver support
  2023-02-23  2:16                   ` zhuyinbo
@ 2023-02-24 19:10                     ` Stephen Boyd
  2023-02-27  1:54                       ` zhuyinbo
  0 siblings, 1 reply; 24+ messages in thread
From: Stephen Boyd @ 2023-02-24 19:10 UTC (permalink / raw)
  To: Huacai Chen, Jianmin Lv, Jiaxun Yang, Krzysztof Kozlowski,
	Michael Turquette, Rob Herring, WANG Xuerui, Yang Li, devicetree,
	linux-clk, linux-kernel, liupeibao, loongarch, wanghongliang,
	zhuyinbo

Quoting zhuyinbo (2023-02-22 18:16:49)
> 
> 在 2023/2/23 上午5:00, Stephen Boyd 写道:
> > Quoting zhuyinbo (2023-02-21 21:10:14)
> >>>>> yes, the use of dts doesn't require the use of CLK_OF_DECLARE and can
> >>>>> use platform_driver_register
> >>>>>
> >>>>> but my drvier not use platform_driver_register to register clk and use
> >>>>> CLK_OF_DECLARE to match of_clk_init.
> >>>> of_clk_init() is there to register clks that are needed for early init,
> >>>> i.e. the clockevent/clocksource or the root interrupt controller
> >>>> (irqchip). Otherwise, it isn't necessary to register clks via
> >>>> of_clk_init().
> >>> okay, I got it.
> >> and,  the time driver  get clock by CCF that ask loongson2 clock driver
> >> use CLK_OF_DECLARE
> >>
> >> to match of_clk_init.   because  the timer_probe  is very early and the
> >> timer driver was use TIMER_OF_DECLARE
> >>
> >> to match time_probe.
> >>
> > If you have a time driver that gets clks, register those early with
> > CLK_OF_DECLARE_DRIVER() and then have a platform driver for the rest of
> > the clk tree that registers clks later.
> 
> okay, I got it.  and this series patch I will use platform driver. 
> later, if the loongson2 time driver use the
> 
> CLK_OF_DECLARE style I will make a alone time clk driver for it that 
> use  CLK_OF_DECLARE_DRIVER()
> 

It can be the same file if you want. But then it can't be a module. Up
to you what you want to do there.

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

* Re: [PATCH v10 2/4] clk: clk-loongson2: add clock controller driver support
  2023-02-24 19:10                     ` Stephen Boyd
@ 2023-02-27  1:54                       ` zhuyinbo
  0 siblings, 0 replies; 24+ messages in thread
From: zhuyinbo @ 2023-02-27  1:54 UTC (permalink / raw)
  To: Stephen Boyd, Huacai Chen, Jianmin Lv, Jiaxun Yang,
	Krzysztof Kozlowski, Michael Turquette, Rob Herring, WANG Xuerui,
	Yang Li, devicetree, linux-clk, linux-kernel, liupeibao,
	loongarch, wanghongliang


在 2023/2/25 上午3:10, Stephen Boyd 写道:
> Quoting zhuyinbo (2023-02-22 18:16:49)
>> 在 2023/2/23 上午5:00, Stephen Boyd 写道:
>>> Quoting zhuyinbo (2023-02-21 21:10:14)
>>>>>>> yes, the use of dts doesn't require the use of CLK_OF_DECLARE and can
>>>>>>> use platform_driver_register
>>>>>>>
>>>>>>> but my drvier not use platform_driver_register to register clk and use
>>>>>>> CLK_OF_DECLARE to match of_clk_init.
>>>>>> of_clk_init() is there to register clks that are needed for early init,
>>>>>> i.e. the clockevent/clocksource or the root interrupt controller
>>>>>> (irqchip). Otherwise, it isn't necessary to register clks via
>>>>>> of_clk_init().
>>>>> okay, I got it.
>>>> and,  the time driver  get clock by CCF that ask loongson2 clock driver
>>>> use CLK_OF_DECLARE
>>>>
>>>> to match of_clk_init.   because  the timer_probe  is very early and the
>>>> timer driver was use TIMER_OF_DECLARE
>>>>
>>>> to match time_probe.
>>>>
>>> If you have a time driver that gets clks, register those early with
>>> CLK_OF_DECLARE_DRIVER() and then have a platform driver for the rest of
>>> the clk tree that registers clks later.
>> okay, I got it.  and this series patch I will use platform driver.
>> later, if the loongson2 time driver use the
>>
>> CLK_OF_DECLARE style I will make a alone time clk driver for it that
>> use  CLK_OF_DECLARE_DRIVER()
>>
> It can be the same file if you want. But then it can't be a module. Up
> to you what you want to do there.
okay, I got it.


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

end of thread, other threads:[~2023-02-27  1:54 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-29  3:41 [PATCH v10 1/4] dt-bindings: clock: add loongson-2 clock include file Yinbo Zhu
2022-11-29  3:41 ` [PATCH v10 2/4] clk: clk-loongson2: add clock controller driver support Yinbo Zhu
2022-11-30  3:32   ` XiaochuanMao
     [not found]   ` <dfc61f0b-0051-4146-f534-6436e3076b65@loongson.cn>
2022-11-30 10:16     ` Yinbo Zhu
2022-11-30 13:14   ` XiaochuanMao
2022-11-30 22:49     ` Yinbo Zhu
2022-12-07  2:15   ` Yinbo Zhu
2023-02-01  4:37   ` zhuyinbo
2023-02-10 23:42   ` Stephen Boyd
2023-02-15  7:35     ` zhuyinbo
2023-02-17 22:15       ` Stephen Boyd
2023-02-20  5:44         ` zhuyinbo
2023-02-21 23:07           ` Stephen Boyd
2023-02-22  2:02             ` zhuyinbo
2023-02-22  5:10               ` zhuyinbo
2023-02-22 21:00                 ` Stephen Boyd
2023-02-23  2:16                   ` zhuyinbo
2023-02-24 19:10                     ` Stephen Boyd
2023-02-27  1:54                       ` zhuyinbo
2022-11-29  3:41 ` [PATCH v10 3/4] LoongArch: time: add of_clk_init in time_init Yinbo Zhu
2023-02-10 23:33   ` Stephen Boyd
2022-11-29  3:41 ` [PATCH v10 4/4] dt-bindings: clock: add loongson-2 clock Yinbo Zhu
2023-02-10 23:43   ` Stephen Boyd
2023-02-10 23:42 ` [PATCH v10 1/4] dt-bindings: clock: add loongson-2 clock include file Stephen Boyd

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