public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [PATCH v6 1/7] mips: loongson: minimal initial SoC support
       [not found] <20260311052046.11265-1-sgdfkk@163.com>
@ 2026-03-11  5:20 ` sgdfkk
  2026-03-11  5:20 ` [PATCH v6 5/7] mips: loongson: add clk driver sgdfkk
  1 sibling, 0 replies; 5+ messages in thread
From: sgdfkk @ 2026-03-11  5:20 UTC (permalink / raw)
  To: duhuanpeng, u-boot; +Cc: chenhuacai, jiaxun.yang, Du Huanpeng

From: Du Huanpeng <u74147@gmail.com>

Loongson 1C is a cost-effective SOC chip for industrial control and
the Internet of Things. The Loongson 1C includes a floating-point
processing unit, supports multiple types of memory, and supports
high-capacity MLC NAND Flash. Loongson 1C provides developers with a
wealth of peripheral interfaces and on-chip modules, including Camera
controller, USB OTG and USB HOST interfaces, AC97/I2S controller, LCD
controller, SPI interface, UART interface, etc., providing sufficient
computing power and multi-application connectivity.

Some highlights of this SoC are:
- Single core LS232, MIPS32 instruction set compatible, main frequency
300MHZ
- 16KB data cache and 16KB instruction cache
- 64 bit float unit, hardware division
- 8/16 bit SDRAM controller, 45 ~ 133MHz
- 8/16 bit SRAM, NAND
- I2S/AC97, LCD, MAC, USB, OTG, SPI, I2C, PWM, CAN, SDIO, ADC
- 12 UARTs

Links:
https://www.loongson.cn/

introduce base support for the ls1c300 SoC.
- debug UART2
- serial console
- clock
- watchdog
- sysreset
- uart

Signed-off-by: Du Huanpeng <u74147@gmail.com>
---
 MAINTAINERS                              |  9 ++++
 arch/mips/Kconfig                        | 11 ++++
 arch/mips/Makefile                       |  1 +
 arch/mips/mach-loongson/Kconfig          | 69 ++++++++++++++++++++++++
 arch/mips/mach-loongson/Makefile         |  6 +++
 arch/mips/mach-loongson/cpu.c            | 19 +++++++
 arch/mips/mach-loongson/ls1c300/Makefile |  7 +++
 arch/mips/mach-loongson/ls1c300/init.c   | 61 +++++++++++++++++++++
 arch/mips/mach-loongson/spl.c            | 46 ++++++++++++++++
 9 files changed, 229 insertions(+)
 create mode 100644 arch/mips/mach-loongson/Kconfig
 create mode 100644 arch/mips/mach-loongson/Makefile
 create mode 100644 arch/mips/mach-loongson/cpu.c
 create mode 100644 arch/mips/mach-loongson/ls1c300/Makefile
 create mode 100644 arch/mips/mach-loongson/ls1c300/init.c
 create mode 100644 arch/mips/mach-loongson/spl.c

diff --git a/MAINTAINERS b/MAINTAINERS
index d2040fee252..d1e6e4bc0da 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1385,6 +1385,15 @@ F:	drivers/net/cortina_ni.c
 F:	drivers/net/cortina_ni.h
 F:	drivers/net/phy/ca_phy.c
 
+MIPS LOONGSON LS1C300
+M:	Du Huanpeng <u74147@gmail.com>
+S:	Maintained
+F:	arch/mips/dts/loongson32-ls1c300b.dtsi
+F:	arch/mips/mach-loongson/
+F:	drivers/clk/loongson/
+F:	drivers/watchdog/loongson_wdt.c
+F:	include/dt-bindings/clock/ls1c300-clk.h
+
 MIPS MEDIATEK
 M:	Weijie Gao <weijie.gao@mediatek.com>
 R:	GSS_MTK_Uboot_upstream <GSS_MTK_Uboot_upstream@mediatek.com>
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 36612756294..0e3fc9ceeb5 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -88,6 +88,16 @@ config ARCH_MTMIPS
 	select SUPPORT_LITTLE_ENDIAN
 	select SUPPORT_SPL
 
+config ARCH_LSMIPS
+	bool "Support Loongson MIPS platforms"
+	select DM
+	select DM_SERIAL
+	select OF_CONTROL
+	select SUPPORTS_CPU_MIPS32_R1
+	select SUPPORTS_CPU_MIPS32_R2
+	select SUPPORTS_LITTLE_ENDIAN
+	select SUPPORT_SPL
+
 config ARCH_JZ47XX
 	bool "Support Ingenic JZ47xx"
 	select SUPPORT_SPL
@@ -202,6 +212,7 @@ source "arch/mips/mach-bmips/Kconfig"
 source "arch/mips/mach-jz47xx/Kconfig"
 source "arch/mips/mach-pic32/Kconfig"
 source "arch/mips/mach-mtmips/Kconfig"
+source "arch/mips/mach-loongson/Kconfig"
 source "arch/mips/mach-octeon/Kconfig"
 
 if MIPS
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 453c7885075..72b800c755b 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -19,6 +19,7 @@ machine-$(CONFIG_ARCH_BMIPS) += bmips
 machine-$(CONFIG_ARCH_JZ47XX) += jz47xx
 machine-$(CONFIG_MACH_PIC32) += pic32
 machine-$(CONFIG_ARCH_MTMIPS) += mtmips
+machine-$(CONFIG_ARCH_LSMIPS) += loongson
 machine-$(CONFIG_ARCH_MSCC) += mscc
 machine-${CONFIG_ARCH_OCTEON} += octeon
 
diff --git a/arch/mips/mach-loongson/Kconfig b/arch/mips/mach-loongson/Kconfig
new file mode 100644
index 00000000000..57d22927270
--- /dev/null
+++ b/arch/mips/mach-loongson/Kconfig
@@ -0,0 +1,69 @@
+menu "Loongson MIPS platforms"
+	depends on ARCH_LSMIPS
+
+config SYS_MALLOC_F_LEN
+	default 0x1000
+
+config SYS_SOC
+	default "ls1c300" if SOC_LS1C300
+
+config SYS_DCACHE_SIZE
+	default 16384
+
+config SYS_DCACHE_LINE_SIZE
+	default 32
+
+config SYS_ICACHE_SIZE
+	default 16384
+
+config SYS_ICACHE_LINE_SIZE
+	default 32
+
+config SPL_PAYLOAD
+	default "u-boot-lzma.img" if SPL_LZMA
+
+config BUILD_TARGET
+	default "u-boot-with-spl.bin" if SPL
+	default "u-boot.bin" if !SPL
+
+choice
+	prompt "Loongson MIPS SoC select"
+
+config SOC_LS1C300
+	bool "LS1C300"
+	select CLK_CCF
+	select SPL_SEPARATE_BSS if SPL
+	select SPL_INIT_STACK_WITHOUT_MALLOC_F if SPL
+	select SPL_LOADER_SUPPORT if SPL
+	select SPL_OF_CONTROL if SPL_DM
+	select SPL_SIMPLE_BUS if SPL_DM
+	select SPL_DM_SERIAL if SPL_DM
+	select SPL_CLK if SPL_DM && SPL_SERIAL
+	select SPL_SYSRESET if SPL_DM
+	select SPL_OF_LIBFDT if SPL_OF_CONTROL
+	help
+	  This supports Loongson LS1C300
+
+endchoice
+
+choice
+	prompt "Board select"
+
+config BOARD_LS1C300
+	bool "Loongson LS1C300 Eval"
+	depends on SOC_LS1C300
+	help
+	  ls1c300-eval board has a LS1C300 SoC with 64MiB of SDRAM
+	  and 512KiB of flash (SPI NOR) and additional NAND storage.
+
+endchoice
+
+config CONS_PIN
+	int "pin group used in uart"
+	default 0
+	help
+	  Select pin group connected to UART for your board.
+
+source "board/loongson/ls1c300-eval/Kconfig"
+
+endmenu
diff --git a/arch/mips/mach-loongson/Makefile b/arch/mips/mach-loongson/Makefile
new file mode 100644
index 00000000000..654143a5f70
--- /dev/null
+++ b/arch/mips/mach-loongson/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-y += cpu.o
+obj-$(CONFIG_SPL_BUILD) += spl.o
+
+obj-$(CONFIG_SOC_LS1C300) += ls1c300/
diff --git a/arch/mips/mach-loongson/cpu.c b/arch/mips/mach-loongson/cpu.c
new file mode 100644
index 00000000000..249fdcbdc5f
--- /dev/null
+++ b/arch/mips/mach-loongson/cpu.c
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Stefan Roese <sr@denx.de>
+ * Copyright (C) 2022-2026 Du Huanpeng <u74147@gmail.com>
+ */
+
+#include <init.h>
+#include <malloc.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/sizes.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int dram_init(void)
+{
+	gd->ram_size = get_ram_size((void *)KSEG1, SZ_256M) - CONFIG_TEXT_BASE % SZ_256M;
+	return 0;
+}
diff --git a/arch/mips/mach-loongson/ls1c300/Makefile b/arch/mips/mach-loongson/ls1c300/Makefile
new file mode 100644
index 00000000000..17b9d6fb9ca
--- /dev/null
+++ b/arch/mips/mach-loongson/ls1c300/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-y += lowlevel_init.o
+obj-y += sdram.o
+obj-y += init.o
+obj-y += gpio.o
+obj-$(CONFIG_SPL_BUILD) += serial.o
diff --git a/arch/mips/mach-loongson/ls1c300/init.c b/arch/mips/mach-loongson/ls1c300/init.c
new file mode 100644
index 00000000000..aea0a863e3e
--- /dev/null
+++ b/arch/mips/mach-loongson/ls1c300/init.c
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 MediaTek Inc.
+ *
+ * Author:  Gao Weijie <weijie.gao@mediatek.com>
+ *
+ * based on: arch/mips/mach-mtmips/mt7628/init.c
+ * Copyright (C) 2020-2026 Du Huanpeng <u74147@gmail.com>
+ */
+
+#include <clk.h>
+#include <dm.h>
+#include <dm/uclass.h>
+#include <dt-bindings/clock/ls1c300-clk.h>
+#include <linux/io.h>
+#include <linux/sizes.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int print_cpuinfo(void)
+{
+	struct udevice *udev;
+	struct clk clk;
+	int ret;
+	ulong xtal;
+	char buf[SZ_32];
+
+	printf("CPU: Loongson ls1c300b\n");
+
+	ret = uclass_get_device_by_driver(UCLASS_CLK, DM_DRIVER_GET(ls1c300_clk), &udev);
+	if (ret) {
+		printf("error: clock driver not found.\n");
+		return 0;
+	}
+
+	clk.dev = udev;
+
+	ret = clk_request(udev, &clk);
+	if (ret < 0)
+		return ret;
+
+	clk.id = CLK_XTAL;
+	xtal = clk_get_rate(&clk);
+
+	clk.id = CLK_CPU_THROT;
+	gd->cpu_clk = clk_get_rate(&clk);
+
+	clk.id = CLK_APB;
+	gd->mem_clk = clk_get_rate(&clk);
+
+	printf("Clock: CPU: %sMHz, ", strmhz(buf, gd->cpu_clk));
+	printf("SDRAM: %sMHz, ", strmhz(buf, gd->mem_clk));
+	printf("XTAL: %sMHz\n", strmhz(buf, xtal));
+
+	return 0;
+}
+
+ulong notrace get_tbclk(void)
+{
+	return gd->cpu_clk / 2;
+}
diff --git a/arch/mips/mach-loongson/spl.c b/arch/mips/mach-loongson/spl.c
new file mode 100644
index 00000000000..40454d2cbc9
--- /dev/null
+++ b/arch/mips/mach-loongson/spl.c
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 MediaTek Inc. All Rights Reserved.
+ *
+ * Author: Gao Weijie <weijie.gao@mediatek.com>
+ *
+ * Copyright (C) 2022-2026 Du Huanpeng <u74147@gmail.com>
+ */
+
+#include <init.h>
+#include <spl.h>
+#include <asm/sections.h>
+#include <linux/libfdt.h>
+#include <linux/sizes.h>
+#include <mach/serial.h>
+
+void __noreturn board_init_f(ulong dummy)
+{
+	spl_init();
+
+#ifdef CONFIG_SPL_SERIAL
+	/*
+	 * loongson_spl_serial_init() is useful if debug uart is enabled,
+	 * or DM based serial is not enabled.
+	 */
+	loongson_spl_serial_init();
+	preloader_console_init();
+#endif
+
+	board_init_r(NULL, 0);
+}
+
+void board_boot_order(u32 *spl_boot_list)
+{
+	spl_boot_list[0] = BOOT_DEVICE_NOR;
+}
+
+unsigned long spl_nor_get_uboot_base(void)
+{
+	void *uboot_base = __image_copy_end;
+
+	if (fdt_magic(uboot_base) == FDT_MAGIC)
+		return (unsigned long)uboot_base + fdt_totalsize(uboot_base);
+
+	return (unsigned long)uboot_base;
+}
-- 
2.43.0


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

* [PATCH v6 5/7] mips: loongson: add clk driver
       [not found] <20260311052046.11265-1-sgdfkk@163.com>
  2026-03-11  5:20 ` [PATCH v6 1/7] mips: loongson: minimal initial SoC support sgdfkk
@ 2026-03-11  5:20 ` sgdfkk
  2026-03-11 17:55   ` Daniel Schwierzeck
  1 sibling, 1 reply; 5+ messages in thread
From: sgdfkk @ 2026-03-11  5:20 UTC (permalink / raw)
  To: duhuanpeng, u-boot; +Cc: chenhuacai, jiaxun.yang, Du Huanpeng

From: Du Huanpeng <u74147@gmail.com>

clk driver loongson mips for embedded SoC ls1c300

Signed-off-by: Du Huanpeng <u74147@gmail.com>
---
 drivers/clk/Makefile               |   1 +
 drivers/clk/loongson/Makefile      |   3 +
 drivers/clk/loongson/clk-ls1c300.c | 179 +++++++++++++++++++++++++++++
 3 files changed, 183 insertions(+)
 create mode 100644 drivers/clk/loongson/Makefile
 create mode 100644 drivers/clk/loongson/clk-ls1c300.c

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 5f0c0d8a5c2..e19bb17276e 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -23,6 +23,7 @@ obj-y += ti/
 obj-$(CONFIG_CLK_THEAD) += thead/
 obj-$(CONFIG_$(PHASE_)CLK_INTEL) += intel/
 obj-$(CONFIG_ARCH_ASPEED) += aspeed/
+obj-$(CONFIG_ARCH_LSMIPS) += loongson/
 obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
 obj-$(CONFIG_ARCH_MESON) += meson/
 obj-$(CONFIG_ARCH_MTMIPS) += mtmips/
diff --git a/drivers/clk/loongson/Makefile b/drivers/clk/loongson/Makefile
new file mode 100644
index 00000000000..0a47269cd30
--- /dev/null
+++ b/drivers/clk/loongson/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_SOC_LS1C300) += clk-ls1c300.o
diff --git a/drivers/clk/loongson/clk-ls1c300.c b/drivers/clk/loongson/clk-ls1c300.c
new file mode 100644
index 00000000000..acca92cd657
--- /dev/null
+++ b/drivers/clk/loongson/clk-ls1c300.c
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * reference:
+ *   drivers/clk/microchip/mpfs_clk.c
+ *   drivers/clk/clk_octeon.c
+ *
+ * Copyright (C) 2020-2026 Du Huanpeng <u74147@gmail.com>
+ */
+
+#include <clk-uclass.h>
+#include <dm.h>
+#include <dt-bindings/clock/ls1c300-clk.h>
+#include <linux/bitops.h>
+#include <linux/bitfield.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+
+/* PLL/SDRAM Frequency Configuration Register */
+#define START_FREQ	0
+#define CLK_DIV_PARAM	4
+
+/* START_FREQ */
+#define	PLL_VALID	BIT(31)
+#define	RESERVED0	GENMASK(30, 24)
+#define	FRAC_N		GENMASK(23, 16)
+#define	M_PLL		GENMASK(15, 8)
+#define	RESERVED1	GENMASK(7, 4)
+#define	RST_TIME	GENMASK(3, 2)
+#define	SDRAM_DIV	GENMASK(1, 0)
+/* CLK_DIV_PARAM */
+#define	PIX_DIV		GENMASK(31, 24)
+#define	CAM_DIV		GENMASK(23, 16)
+#define	CPU_DIV		GENMASK(15, 8)
+#define	RESERVED2	GENMASK(7, 6)
+#define	PIX_DIV_VALID	BIT(5)
+#define	PIX_SEL		BIT(4)
+#define	CAM_DIV_VALID	BIT(3)
+#define	CAM_SEL		BIT(2)
+#define	CPU_DIV_VALID	BIT(1)
+#define	CPU_SEL		BIT(0)
+/* CPU_THROT */
+#define	CPU_THROT	GENMASK(3, 0)
+
+static const struct clk_div_table sdram_div_table[] = {
+	{.val = 0, .div = 2},
+	{.val = 1, .div = 4},
+	{.val = 2, .div = 3},
+	{.val = 3, .div = 3},
+};
+
+ulong ls1c300_pll_get_rate(struct clk *clk)
+{
+	unsigned int mult;
+	long long parent_rate;
+	void *base;
+	unsigned int val;
+
+	parent_rate = clk_get_parent_rate(clk);
+	base = (void *)clk->data;
+
+	val = readl(base + START_FREQ);
+	mult = FIELD_GET(FRAC_N, val) + FIELD_GET(M_PLL, val);
+	return (mult * parent_rate) / 4;
+}
+
+static ulong ls1c300_clk_get_rate(struct clk *clk)
+{
+	struct clk *cl;
+	ulong rate;
+	int err;
+
+	err = clk_get_by_id(clk->id, &cl);
+	if (err)
+		return err;
+
+	rate = clk_get_rate(cl);
+	return rate;
+}
+
+static int ls1c300_clk_probe(struct udevice *dev)
+{
+	void __iomem *base;
+	void __iomem *cpu_throt;
+	void __iomem *addr;
+
+	struct clk *cl, clk;
+	const char *parent_name;
+	int flags;
+	int ret;
+
+	base = (void *)dev_remap_addr_index(dev, 0);
+	cpu_throt  = (void *)dev_remap_addr_index(dev, 1);
+
+	ret = clk_get_by_index(dev, 0, &clk);
+	if (ret)
+		return ret;
+
+	ret = clk_get_rate(&clk);
+
+	parent_name = clk.dev->name;
+
+	cl = kzalloc(sizeof(*cl), GFP_KERNEL);
+	cl->data = (unsigned long)base;
+	ret = clk_register(cl, "clk_ls1c300_pll", "pll", parent_name);
+	clk_dm(CLK_PLL, cl);
+
+	addr = base + CLK_DIV_PARAM;
+	flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO;
+	cl = clk_register_divider(NULL, "cpu_div", "pll", 0, addr,  8, 7, flags);
+	clk_dm(CLK_CPU, cl);
+	cl = clk_register_divider(NULL, "cam_div", "pll", 0, addr, 16, 7, flags);
+	clk_dm(CLK_CAMERA, cl);
+	cl = clk_register_divider(NULL, "pix_div", "pll", 0, addr, 24, 7, flags);
+	clk_dm(CLK_PIX, cl);
+
+	cl = kzalloc(sizeof(*cl), GFP_KERNEL);
+	cl->data = (unsigned long)cpu_throt;
+	ret = clk_register(cl, "clk_cpu_throt", "cpu_throt_factor", "cpu_div");
+	clk_dm(CLK_CPU_THROT, cl);
+
+	addr = base + START_FREQ;
+	cl = clk_register_divider(NULL, "sdram_div", "cpu_div", 0, addr, 0, 2, 0);
+	to_clk_divider(cl)->table = sdram_div_table;
+	clk_dm(CLK_APB, cl);
+
+	return 0;
+}
+
+static ulong cpu_throt_get_rate(struct clk *clk)
+{
+	void __iomem *cpu_throt;
+	long long parent_rate;
+	ulong ret;
+
+	parent_rate = clk_get_parent_rate(clk);
+	cpu_throt = (void *)clk->data;
+
+	ret = readl(cpu_throt) + 1;
+	ret = parent_rate * ret / 16;
+	return ret;
+}
+
+static const struct udevice_id ls1c300_clk_ids[] = {
+	{ .compatible = "loongson,ls1c300-clk" },
+	{ }
+};
+
+static const struct clk_ops clk_cpu_throt_ops = {
+	.get_rate = cpu_throt_get_rate,
+};
+
+static const struct clk_ops clk_ls1c300_pll_ops = {
+	.get_rate = ls1c300_pll_get_rate,
+};
+
+static const struct clk_ops ls1c300_clk_ops = {
+	.get_rate = ls1c300_clk_get_rate,
+};
+
+U_BOOT_DRIVER(clk_ls1c300_cpu_throt) = {
+	.name	= "clk_cpu_throt",
+	.id	= UCLASS_CLK,
+	.ops	= &clk_cpu_throt_ops,
+};
+
+U_BOOT_DRIVER(clk_ls1c300_pll) = {
+	.name	= "clk_ls1c300_pll",
+	.id	= UCLASS_CLK,
+	.ops	= &clk_ls1c300_pll_ops,
+};
+
+U_BOOT_DRIVER(ls1c300_clk) = {
+	.name = "clk_ls1c300",
+	.id = UCLASS_CLK,
+	.of_match = ls1c300_clk_ids,
+	.probe = ls1c300_clk_probe,
+	.priv_auto = sizeof(struct clk),
+	.ops = &ls1c300_clk_ops,
+};
-- 
2.43.0


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

* [PATCH v6 5/7] mips: loongson: add clk driver
  2026-03-11  8:41 [PATCH v6 0/7] add loongson mips ls1c300 initial support sgdfkk
@ 2026-03-11  8:41 ` sgdfkk
  0 siblings, 0 replies; 5+ messages in thread
From: sgdfkk @ 2026-03-11  8:41 UTC (permalink / raw)
  To: duhuanpeng, u-boot; +Cc: chenhuacai, jiaxun.yang, Du Huanpeng

From: Du Huanpeng <u74147@gmail.com>

clk driver loongson mips for embedded SoC ls1c300

Signed-off-by: Du Huanpeng <u74147@gmail.com>
---
 drivers/clk/Makefile               |   1 +
 drivers/clk/loongson/Makefile      |   3 +
 drivers/clk/loongson/clk-ls1c300.c | 179 +++++++++++++++++++++++++++++
 3 files changed, 183 insertions(+)
 create mode 100644 drivers/clk/loongson/Makefile
 create mode 100644 drivers/clk/loongson/clk-ls1c300.c

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 5f0c0d8a5c2..e19bb17276e 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -23,6 +23,7 @@ obj-y += ti/
 obj-$(CONFIG_CLK_THEAD) += thead/
 obj-$(CONFIG_$(PHASE_)CLK_INTEL) += intel/
 obj-$(CONFIG_ARCH_ASPEED) += aspeed/
+obj-$(CONFIG_ARCH_LSMIPS) += loongson/
 obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
 obj-$(CONFIG_ARCH_MESON) += meson/
 obj-$(CONFIG_ARCH_MTMIPS) += mtmips/
diff --git a/drivers/clk/loongson/Makefile b/drivers/clk/loongson/Makefile
new file mode 100644
index 00000000000..0a47269cd30
--- /dev/null
+++ b/drivers/clk/loongson/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_SOC_LS1C300) += clk-ls1c300.o
diff --git a/drivers/clk/loongson/clk-ls1c300.c b/drivers/clk/loongson/clk-ls1c300.c
new file mode 100644
index 00000000000..acca92cd657
--- /dev/null
+++ b/drivers/clk/loongson/clk-ls1c300.c
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * reference:
+ *   drivers/clk/microchip/mpfs_clk.c
+ *   drivers/clk/clk_octeon.c
+ *
+ * Copyright (C) 2020-2026 Du Huanpeng <u74147@gmail.com>
+ */
+
+#include <clk-uclass.h>
+#include <dm.h>
+#include <dt-bindings/clock/ls1c300-clk.h>
+#include <linux/bitops.h>
+#include <linux/bitfield.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+
+/* PLL/SDRAM Frequency Configuration Register */
+#define START_FREQ	0
+#define CLK_DIV_PARAM	4
+
+/* START_FREQ */
+#define	PLL_VALID	BIT(31)
+#define	RESERVED0	GENMASK(30, 24)
+#define	FRAC_N		GENMASK(23, 16)
+#define	M_PLL		GENMASK(15, 8)
+#define	RESERVED1	GENMASK(7, 4)
+#define	RST_TIME	GENMASK(3, 2)
+#define	SDRAM_DIV	GENMASK(1, 0)
+/* CLK_DIV_PARAM */
+#define	PIX_DIV		GENMASK(31, 24)
+#define	CAM_DIV		GENMASK(23, 16)
+#define	CPU_DIV		GENMASK(15, 8)
+#define	RESERVED2	GENMASK(7, 6)
+#define	PIX_DIV_VALID	BIT(5)
+#define	PIX_SEL		BIT(4)
+#define	CAM_DIV_VALID	BIT(3)
+#define	CAM_SEL		BIT(2)
+#define	CPU_DIV_VALID	BIT(1)
+#define	CPU_SEL		BIT(0)
+/* CPU_THROT */
+#define	CPU_THROT	GENMASK(3, 0)
+
+static const struct clk_div_table sdram_div_table[] = {
+	{.val = 0, .div = 2},
+	{.val = 1, .div = 4},
+	{.val = 2, .div = 3},
+	{.val = 3, .div = 3},
+};
+
+ulong ls1c300_pll_get_rate(struct clk *clk)
+{
+	unsigned int mult;
+	long long parent_rate;
+	void *base;
+	unsigned int val;
+
+	parent_rate = clk_get_parent_rate(clk);
+	base = (void *)clk->data;
+
+	val = readl(base + START_FREQ);
+	mult = FIELD_GET(FRAC_N, val) + FIELD_GET(M_PLL, val);
+	return (mult * parent_rate) / 4;
+}
+
+static ulong ls1c300_clk_get_rate(struct clk *clk)
+{
+	struct clk *cl;
+	ulong rate;
+	int err;
+
+	err = clk_get_by_id(clk->id, &cl);
+	if (err)
+		return err;
+
+	rate = clk_get_rate(cl);
+	return rate;
+}
+
+static int ls1c300_clk_probe(struct udevice *dev)
+{
+	void __iomem *base;
+	void __iomem *cpu_throt;
+	void __iomem *addr;
+
+	struct clk *cl, clk;
+	const char *parent_name;
+	int flags;
+	int ret;
+
+	base = (void *)dev_remap_addr_index(dev, 0);
+	cpu_throt  = (void *)dev_remap_addr_index(dev, 1);
+
+	ret = clk_get_by_index(dev, 0, &clk);
+	if (ret)
+		return ret;
+
+	ret = clk_get_rate(&clk);
+
+	parent_name = clk.dev->name;
+
+	cl = kzalloc(sizeof(*cl), GFP_KERNEL);
+	cl->data = (unsigned long)base;
+	ret = clk_register(cl, "clk_ls1c300_pll", "pll", parent_name);
+	clk_dm(CLK_PLL, cl);
+
+	addr = base + CLK_DIV_PARAM;
+	flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO;
+	cl = clk_register_divider(NULL, "cpu_div", "pll", 0, addr,  8, 7, flags);
+	clk_dm(CLK_CPU, cl);
+	cl = clk_register_divider(NULL, "cam_div", "pll", 0, addr, 16, 7, flags);
+	clk_dm(CLK_CAMERA, cl);
+	cl = clk_register_divider(NULL, "pix_div", "pll", 0, addr, 24, 7, flags);
+	clk_dm(CLK_PIX, cl);
+
+	cl = kzalloc(sizeof(*cl), GFP_KERNEL);
+	cl->data = (unsigned long)cpu_throt;
+	ret = clk_register(cl, "clk_cpu_throt", "cpu_throt_factor", "cpu_div");
+	clk_dm(CLK_CPU_THROT, cl);
+
+	addr = base + START_FREQ;
+	cl = clk_register_divider(NULL, "sdram_div", "cpu_div", 0, addr, 0, 2, 0);
+	to_clk_divider(cl)->table = sdram_div_table;
+	clk_dm(CLK_APB, cl);
+
+	return 0;
+}
+
+static ulong cpu_throt_get_rate(struct clk *clk)
+{
+	void __iomem *cpu_throt;
+	long long parent_rate;
+	ulong ret;
+
+	parent_rate = clk_get_parent_rate(clk);
+	cpu_throt = (void *)clk->data;
+
+	ret = readl(cpu_throt) + 1;
+	ret = parent_rate * ret / 16;
+	return ret;
+}
+
+static const struct udevice_id ls1c300_clk_ids[] = {
+	{ .compatible = "loongson,ls1c300-clk" },
+	{ }
+};
+
+static const struct clk_ops clk_cpu_throt_ops = {
+	.get_rate = cpu_throt_get_rate,
+};
+
+static const struct clk_ops clk_ls1c300_pll_ops = {
+	.get_rate = ls1c300_pll_get_rate,
+};
+
+static const struct clk_ops ls1c300_clk_ops = {
+	.get_rate = ls1c300_clk_get_rate,
+};
+
+U_BOOT_DRIVER(clk_ls1c300_cpu_throt) = {
+	.name	= "clk_cpu_throt",
+	.id	= UCLASS_CLK,
+	.ops	= &clk_cpu_throt_ops,
+};
+
+U_BOOT_DRIVER(clk_ls1c300_pll) = {
+	.name	= "clk_ls1c300_pll",
+	.id	= UCLASS_CLK,
+	.ops	= &clk_ls1c300_pll_ops,
+};
+
+U_BOOT_DRIVER(ls1c300_clk) = {
+	.name = "clk_ls1c300",
+	.id = UCLASS_CLK,
+	.of_match = ls1c300_clk_ids,
+	.probe = ls1c300_clk_probe,
+	.priv_auto = sizeof(struct clk),
+	.ops = &ls1c300_clk_ops,
+};
-- 
2.43.0


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

* Re: [PATCH v6 5/7] mips: loongson: add clk driver
  2026-03-11  5:20 ` [PATCH v6 5/7] mips: loongson: add clk driver sgdfkk
@ 2026-03-11 17:55   ` Daniel Schwierzeck
  2026-04-07 15:41     ` duhuanpeng
  0 siblings, 1 reply; 5+ messages in thread
From: Daniel Schwierzeck @ 2026-03-11 17:55 UTC (permalink / raw)
  To: sgdfkk, duhuanpeng, u-boot; +Cc: chenhuacai, jiaxun.yang, Du Huanpeng



On 3/11/26 06:20, sgdfkk@163.com wrote:
> From: Du Huanpeng <u74147@gmail.com>
> 
> clk driver loongson mips for embedded SoC ls1c300
> 
> Signed-off-by: Du Huanpeng <u74147@gmail.com>
> ---
>   drivers/clk/Makefile               |   1 +
>   drivers/clk/loongson/Makefile      |   3 +
>   drivers/clk/loongson/clk-ls1c300.c | 179 +++++++++++++++++++++++++++++
>   3 files changed, 183 insertions(+)
>   create mode 100644 drivers/clk/loongson/Makefile
>   create mode 100644 drivers/clk/loongson/clk-ls1c300.c
> 
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 5f0c0d8a5c2..e19bb17276e 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -23,6 +23,7 @@ obj-y += ti/
>   obj-$(CONFIG_CLK_THEAD) += thead/
>   obj-$(CONFIG_$(PHASE_)CLK_INTEL) += intel/
>   obj-$(CONFIG_ARCH_ASPEED) += aspeed/
> +obj-$(CONFIG_ARCH_LSMIPS) += loongson/
>   obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
>   obj-$(CONFIG_ARCH_MESON) += meson/
>   obj-$(CONFIG_ARCH_MTMIPS) += mtmips/
> diff --git a/drivers/clk/loongson/Makefile b/drivers/clk/loongson/Makefile
> new file mode 100644
> index 00000000000..0a47269cd30
> --- /dev/null
> +++ b/drivers/clk/loongson/Makefile
> @@ -0,0 +1,3 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +obj-$(CONFIG_SOC_LS1C300) += clk-ls1c300.o
> diff --git a/drivers/clk/loongson/clk-ls1c300.c b/drivers/clk/loongson/clk-ls1c300.c
> new file mode 100644
> index 00000000000..acca92cd657
> --- /dev/null
> +++ b/drivers/clk/loongson/clk-ls1c300.c
> @@ -0,0 +1,179 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * reference:
> + *   drivers/clk/microchip/mpfs_clk.c
> + *   drivers/clk/clk_octeon.c
> + *
> + * Copyright (C) 2020-2026 Du Huanpeng <u74147@gmail.com>
> + */
> +
> +#include <clk-uclass.h>
> +#include <dm.h>
> +#include <dt-bindings/clock/ls1c300-clk.h>
> +#include <linux/bitops.h>
> +#include <linux/bitfield.h>
> +#include <linux/io.h>
> +#include <linux/clk-provider.h>
> +
> +/* PLL/SDRAM Frequency Configuration Register */
> +#define START_FREQ	0
> +#define CLK_DIV_PARAM	4
> +
> +/* START_FREQ */
> +#define	PLL_VALID	BIT(31)
> +#define	RESERVED0	GENMASK(30, 24)
> +#define	FRAC_N		GENMASK(23, 16)
> +#define	M_PLL		GENMASK(15, 8)
> +#define	RESERVED1	GENMASK(7, 4)
> +#define	RST_TIME	GENMASK(3, 2)
> +#define	SDRAM_DIV	GENMASK(1, 0)
> +/* CLK_DIV_PARAM */
> +#define	PIX_DIV		GENMASK(31, 24)
> +#define	CAM_DIV		GENMASK(23, 16)
> +#define	CPU_DIV		GENMASK(15, 8)
> +#define	RESERVED2	GENMASK(7, 6)
> +#define	PIX_DIV_VALID	BIT(5)
> +#define	PIX_SEL		BIT(4)
> +#define	CAM_DIV_VALID	BIT(3)
> +#define	CAM_SEL		BIT(2)
> +#define	CPU_DIV_VALID	BIT(1)
> +#define	CPU_SEL		BIT(0)
> +/* CPU_THROT */
> +#define	CPU_THROT	GENMASK(3, 0)
> +
> +static const struct clk_div_table sdram_div_table[] = {
> +	{.val = 0, .div = 2},
> +	{.val = 1, .div = 4},
> +	{.val = 2, .div = 3},
> +	{.val = 3, .div = 3},
> +};
> +
> +ulong ls1c300_pll_get_rate(struct clk *clk)
> +{
> +	unsigned int mult;
> +	long long parent_rate;
> +	void *base;
> +	unsigned int val;
> +
> +	parent_rate = clk_get_parent_rate(clk);
> +	base = (void *)clk->data;
> +
> +	val = readl(base + START_FREQ);
> +	mult = FIELD_GET(FRAC_N, val) + FIELD_GET(M_PLL, val);
> +	return (mult * parent_rate) / 4;
> +}
> +
> +static ulong ls1c300_clk_get_rate(struct clk *clk)
> +{
> +	struct clk *cl;
> +	ulong rate;
> +	int err;
> +
> +	err = clk_get_by_id(clk->id, &cl);
> +	if (err)
> +		return err;
> +
> +	rate = clk_get_rate(cl);
> +	return rate;
> +}
> +
> +static int ls1c300_clk_probe(struct udevice *dev)
> +{
> +	void __iomem *base;
> +	void __iomem *cpu_throt;
> +	void __iomem *addr;
> +
> +	struct clk *cl, clk;
> +	const char *parent_name;
> +	int flags;
> +	int ret;
> +
> +	base = (void *)dev_remap_addr_index(dev, 0);
> +	cpu_throt  = (void *)dev_remap_addr_index(dev, 1);

no casting required, return value is already "void __iomem *"

> +
> +	ret = clk_get_by_index(dev, 0, &clk);
> +	if (ret)
> +		return ret;
> +
> +	ret = clk_get_rate(&clk);
> +
> +	parent_name = clk.dev->name;
> +
> +	cl = kzalloc(sizeof(*cl), GFP_KERNEL);
> +	cl->data = (unsigned long)base;

why not create a "struct ls1c300_clk_priv" which embeds stuff like "void 
__iomem *base" and just use "struct ls1c300_clk_priv *priv = 
dev_get_priv(dev);" to get a type-safe pointer to the auto-allocated 
memory? The platform driver itself should not fiddle with "struct clk" 
and just register "struct clk_ops".

> +	ret = clk_register(cl, "clk_ls1c300_pll", "pll", parent_name);
> +	clk_dm(CLK_PLL, cl);
> +
> +	addr = base + CLK_DIV_PARAM;
> +	flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO;
> +	cl = clk_register_divider(NULL, "cpu_div", "pll", 0, addr,  8, 7, flags);
> +	clk_dm(CLK_CPU, cl);
> +	cl = clk_register_divider(NULL, "cam_div", "pll", 0, addr, 16, 7, flags);
> +	clk_dm(CLK_CAMERA, cl);
> +	cl = clk_register_divider(NULL, "pix_div", "pll", 0, addr, 24, 7, flags);
> +	clk_dm(CLK_PIX, cl);
> +
> +	cl = kzalloc(sizeof(*cl), GFP_KERNEL);
> +	cl->data = (unsigned long)cpu_throt;
> +	ret = clk_register(cl, "clk_cpu_throt", "cpu_throt_factor", "cpu_div");
> +	clk_dm(CLK_CPU_THROT, cl);
> +
> +	addr = base + START_FREQ;
> +	cl = clk_register_divider(NULL, "sdram_div", "cpu_div", 0, addr, 0, 2, 0);
> +	to_clk_divider(cl)->table = sdram_div_table;
> +	clk_dm(CLK_APB, cl);
> +
> +	return 0;
> +}
> +
> +static ulong cpu_throt_get_rate(struct clk *clk)
> +{
> +	void __iomem *cpu_throt;
> +	long long parent_rate;
> +	ulong ret;
> +
> +	parent_rate = clk_get_parent_rate(clk);
> +	cpu_throt = (void *)clk->data;
> +
> +	ret = readl(cpu_throt) + 1;
> +	ret = parent_rate * ret / 16;
> +	return ret;
> +}
> +
> +static const struct udevice_id ls1c300_clk_ids[] = {
> +	{ .compatible = "loongson,ls1c300-clk" },
> +	{ }
> +};
> +
> +static const struct clk_ops clk_cpu_throt_ops = {
> +	.get_rate = cpu_throt_get_rate,
> +};
> +
> +static const struct clk_ops clk_ls1c300_pll_ops = {
> +	.get_rate = ls1c300_pll_get_rate,
> +};
> +
> +static const struct clk_ops ls1c300_clk_ops = {
> +	.get_rate = ls1c300_clk_get_rate,
> +};
> +
> +U_BOOT_DRIVER(clk_ls1c300_cpu_throt) = {
> +	.name	= "clk_cpu_throt",
> +	.id	= UCLASS_CLK,
> +	.ops	= &clk_cpu_throt_ops,
> +};
> +
> +U_BOOT_DRIVER(clk_ls1c300_pll) = {
> +	.name	= "clk_ls1c300_pll",
> +	.id	= UCLASS_CLK,
> +	.ops	= &clk_ls1c300_pll_ops,
> +};
> +
> +U_BOOT_DRIVER(ls1c300_clk) = {
> +	.name = "clk_ls1c300",
> +	.id = UCLASS_CLK,
> +	.of_match = ls1c300_clk_ids,
> +	.probe = ls1c300_clk_probe,
> +	.priv_auto = sizeof(struct clk),
> +	.ops = &ls1c300_clk_ops,
> +};

-- 
- Daniel


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

* Re: [PATCH v6 5/7] mips: loongson: add clk driver
  2026-03-11 17:55   ` Daniel Schwierzeck
@ 2026-04-07 15:41     ` duhuanpeng
  0 siblings, 0 replies; 5+ messages in thread
From: duhuanpeng @ 2026-04-07 15:41 UTC (permalink / raw)
  To: Daniel Schwierzeck; +Cc: sgdfkk, u-boot, chenhuacai, jiaxun.yang, Du Huanpeng

Dear Daniel,

On Wed, Mar 11, 2026 at 06:55:31PM +0100, Daniel Schwierzeck wrote:
> 
> 
> On 3/11/26 06:20, sgdfkk@163.com wrote:
> > From: Du Huanpeng <u74147@gmail.com>
> > 
> > clk driver loongson mips for embedded SoC ls1c300
> > 
> > Signed-off-by: Du Huanpeng <u74147@gmail.com>
> > ---
> >   drivers/clk/Makefile               |   1 +
> >   drivers/clk/loongson/Makefile      |   3 +
> >   drivers/clk/loongson/clk-ls1c300.c | 179 +++++++++++++++++++++++++++++
> >   3 files changed, 183 insertions(+)
> >   create mode 100644 drivers/clk/loongson/Makefile
> >   create mode 100644 drivers/clk/loongson/clk-ls1c300.c
> > 
> > diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> > index 5f0c0d8a5c2..e19bb17276e 100644
> > --- a/drivers/clk/Makefile
> > +++ b/drivers/clk/Makefile
> > @@ -23,6 +23,7 @@ obj-y += ti/
> >   obj-$(CONFIG_CLK_THEAD) += thead/
> >   obj-$(CONFIG_$(PHASE_)CLK_INTEL) += intel/
> >   obj-$(CONFIG_ARCH_ASPEED) += aspeed/
> > +obj-$(CONFIG_ARCH_LSMIPS) += loongson/
> >   obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
> >   obj-$(CONFIG_ARCH_MESON) += meson/
> >   obj-$(CONFIG_ARCH_MTMIPS) += mtmips/
> > diff --git a/drivers/clk/loongson/Makefile b/drivers/clk/loongson/Makefile
> > new file mode 100644
> > index 00000000000..0a47269cd30
> > --- /dev/null
> > +++ b/drivers/clk/loongson/Makefile
> > @@ -0,0 +1,3 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +
> > +obj-$(CONFIG_SOC_LS1C300) += clk-ls1c300.o
> > diff --git a/drivers/clk/loongson/clk-ls1c300.c b/drivers/clk/loongson/clk-ls1c300.c
> > new file mode 100644
> > index 00000000000..acca92cd657
> > --- /dev/null
> > +++ b/drivers/clk/loongson/clk-ls1c300.c
> > @@ -0,0 +1,179 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * reference:
> > + *   drivers/clk/microchip/mpfs_clk.c
> > + *   drivers/clk/clk_octeon.c
> > + *
> > + * Copyright (C) 2020-2026 Du Huanpeng <u74147@gmail.com>
> > + */
> > +
> > +#include <clk-uclass.h>
> > +#include <dm.h>
> > +#include <dt-bindings/clock/ls1c300-clk.h>
> > +#include <linux/bitops.h>
> > +#include <linux/bitfield.h>
> > +#include <linux/io.h>
> > +#include <linux/clk-provider.h>
> > +
> > +/* PLL/SDRAM Frequency Configuration Register */
> > +#define START_FREQ	0
> > +#define CLK_DIV_PARAM	4
> > +
> > +/* START_FREQ */
> > +#define	PLL_VALID	BIT(31)
> > +#define	RESERVED0	GENMASK(30, 24)
> > +#define	FRAC_N		GENMASK(23, 16)
> > +#define	M_PLL		GENMASK(15, 8)
> > +#define	RESERVED1	GENMASK(7, 4)
> > +#define	RST_TIME	GENMASK(3, 2)
> > +#define	SDRAM_DIV	GENMASK(1, 0)
> > +/* CLK_DIV_PARAM */
> > +#define	PIX_DIV		GENMASK(31, 24)
> > +#define	CAM_DIV		GENMASK(23, 16)
> > +#define	CPU_DIV		GENMASK(15, 8)
> > +#define	RESERVED2	GENMASK(7, 6)
> > +#define	PIX_DIV_VALID	BIT(5)
> > +#define	PIX_SEL		BIT(4)
> > +#define	CAM_DIV_VALID	BIT(3)
> > +#define	CAM_SEL		BIT(2)
> > +#define	CPU_DIV_VALID	BIT(1)
> > +#define	CPU_SEL		BIT(0)
> > +/* CPU_THROT */
> > +#define	CPU_THROT	GENMASK(3, 0)
> > +
> > +static const struct clk_div_table sdram_div_table[] = {
> > +	{.val = 0, .div = 2},
> > +	{.val = 1, .div = 4},
> > +	{.val = 2, .div = 3},
> > +	{.val = 3, .div = 3},
> > +};
> > +
> > +ulong ls1c300_pll_get_rate(struct clk *clk)
> > +{
> > +	unsigned int mult;
> > +	long long parent_rate;
> > +	void *base;
> > +	unsigned int val;
> > +
> > +	parent_rate = clk_get_parent_rate(clk);
> > +	base = (void *)clk->data;
> > +
> > +	val = readl(base + START_FREQ);
> > +	mult = FIELD_GET(FRAC_N, val) + FIELD_GET(M_PLL, val);
> > +	return (mult * parent_rate) / 4;
> > +}
> > +
> > +static ulong ls1c300_clk_get_rate(struct clk *clk)
> > +{
> > +	struct clk *cl;
> > +	ulong rate;
> > +	int err;
> > +
> > +	err = clk_get_by_id(clk->id, &cl);
> > +	if (err)
> > +		return err;
> > +
> > +	rate = clk_get_rate(cl);
> > +	return rate;
> > +}
> > +
> > +static int ls1c300_clk_probe(struct udevice *dev)
> > +{
> > +	void __iomem *base;
> > +	void __iomem *cpu_throt;
> > +	void __iomem *addr;
> > +
> > +	struct clk *cl, clk;
> > +	const char *parent_name;
> > +	int flags;
> > +	int ret;
> > +
> > +	base = (void *)dev_remap_addr_index(dev, 0);
> > +	cpu_throt  = (void *)dev_remap_addr_index(dev, 1);
> 
> no casting required, return value is already "void __iomem *"
fixed.


> 
> > +
> > +	ret = clk_get_by_index(dev, 0, &clk);
> > +	if (ret)
> > +		return ret;
> > +
> > +	ret = clk_get_rate(&clk);
> > +
> > +	parent_name = clk.dev->name;
> > +
> > +	cl = kzalloc(sizeof(*cl), GFP_KERNEL);
> > +	cl->data = (unsigned long)base;
> 
> why not create a "struct ls1c300_clk_priv" which embeds stuff like "void
> __iomem *base" and just use "struct ls1c300_clk_priv *priv =
> dev_get_priv(dev);" to get a type-safe pointer to the auto-allocated memory?
> The platform driver itself should not fiddle with "struct clk" and just
> register "struct clk_ops".
driver is updated here:
https://lists.denx.de/pipermail/u-boot/2026-April/613978.html

> 
> > +	ret = clk_register(cl, "clk_ls1c300_pll", "pll", parent_name);
> > +	clk_dm(CLK_PLL, cl);
> > +
> > +	addr = base + CLK_DIV_PARAM;
> > +	flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO;
> > +	cl = clk_register_divider(NULL, "cpu_div", "pll", 0, addr,  8, 7, flags);
> > +	clk_dm(CLK_CPU, cl);
> > +	cl = clk_register_divider(NULL, "cam_div", "pll", 0, addr, 16, 7, flags);
> > +	clk_dm(CLK_CAMERA, cl);
> > +	cl = clk_register_divider(NULL, "pix_div", "pll", 0, addr, 24, 7, flags);
> > +	clk_dm(CLK_PIX, cl);
> > +
> > +	cl = kzalloc(sizeof(*cl), GFP_KERNEL);
> > +	cl->data = (unsigned long)cpu_throt;
> > +	ret = clk_register(cl, "clk_cpu_throt", "cpu_throt_factor", "cpu_div");
> > +	clk_dm(CLK_CPU_THROT, cl);
> > +
> > +	addr = base + START_FREQ;
> > +	cl = clk_register_divider(NULL, "sdram_div", "cpu_div", 0, addr, 0, 2, 0);
> > +	to_clk_divider(cl)->table = sdram_div_table;
> > +	clk_dm(CLK_APB, cl);
> > +
> > +	return 0;
> > +}
> > +
> > +static ulong cpu_throt_get_rate(struct clk *clk)
> > +{
> > +	void __iomem *cpu_throt;
> > +	long long parent_rate;
> > +	ulong ret;
> > +
> > +	parent_rate = clk_get_parent_rate(clk);
> > +	cpu_throt = (void *)clk->data;
> > +
> > +	ret = readl(cpu_throt) + 1;
> > +	ret = parent_rate * ret / 16;
> > +	return ret;
> > +}
> > +
> > +static const struct udevice_id ls1c300_clk_ids[] = {
> > +	{ .compatible = "loongson,ls1c300-clk" },
> > +	{ }
> > +};
> > +
> > +static const struct clk_ops clk_cpu_throt_ops = {
> > +	.get_rate = cpu_throt_get_rate,
> > +};
> > +
> > +static const struct clk_ops clk_ls1c300_pll_ops = {
> > +	.get_rate = ls1c300_pll_get_rate,
> > +};
> > +
> > +static const struct clk_ops ls1c300_clk_ops = {
> > +	.get_rate = ls1c300_clk_get_rate,
> > +};
> > +
> > +U_BOOT_DRIVER(clk_ls1c300_cpu_throt) = {
> > +	.name	= "clk_cpu_throt",
> > +	.id	= UCLASS_CLK,
> > +	.ops	= &clk_cpu_throt_ops,
> > +};
> > +
> > +U_BOOT_DRIVER(clk_ls1c300_pll) = {
> > +	.name	= "clk_ls1c300_pll",
> > +	.id	= UCLASS_CLK,
> > +	.ops	= &clk_ls1c300_pll_ops,
> > +};
> > +
> > +U_BOOT_DRIVER(ls1c300_clk) = {
> > +	.name = "clk_ls1c300",
> > +	.id = UCLASS_CLK,
> > +	.of_match = ls1c300_clk_ids,
> > +	.probe = ls1c300_clk_probe,
> > +	.priv_auto = sizeof(struct clk),
> > +	.ops = &ls1c300_clk_ops,
> > +};
> 
> -- 
> - Daniel
> 


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

end of thread, other threads:[~2026-04-07 21:23 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20260311052046.11265-1-sgdfkk@163.com>
2026-03-11  5:20 ` [PATCH v6 1/7] mips: loongson: minimal initial SoC support sgdfkk
2026-03-11  5:20 ` [PATCH v6 5/7] mips: loongson: add clk driver sgdfkk
2026-03-11 17:55   ` Daniel Schwierzeck
2026-04-07 15:41     ` duhuanpeng
2026-03-11  8:41 [PATCH v6 0/7] add loongson mips ls1c300 initial support sgdfkk
2026-03-11  8:41 ` [PATCH v6 5/7] mips: loongson: add clk driver sgdfkk

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox