* [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