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