Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F163457343
D57732.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
76 KB
Referenced Files
None
Subscribers
None
D57732.diff
View Options
diff --git a/sys/arm64/conf/GENERIC b/sys/arm64/conf/GENERIC
--- a/sys/arm64/conf/GENERIC
+++ b/sys/arm64/conf/GENERIC
@@ -38,6 +38,7 @@
include "std.hisilicon"
include "std.imx"
include "std.marvell"
+include "std.mediatek"
include "std.nvidia"
include "std.nxp"
include "std.qcom"
diff --git a/sys/arm64/conf/MEDIATEK b/sys/arm64/conf/MEDIATEK
new file mode 100644
--- /dev/null
+++ b/sys/arm64/conf/MEDIATEK
@@ -0,0 +1,38 @@
+#
+# MEDIATEK -- Mediatek kernel configuration file for FreeBSD/arm64
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# https://docs.freebsd.org/en/books/handbook/kernelconfig/#kernelconfig-config
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (https://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+
+#NO_UNIVERSE
+
+cpu ARM64
+ident MEDIATEK
+
+makeoptions DEBUG=-g # Enable kernel debugging sybmbols
+makeoptions WITH_KERNEL_BIN=1
+
+options EARLY_PRINTF=ns8250
+options SOCDEV_PA=0x11002000
+options UART_NS8250_EARLY_REG_SHIFT=2
+options UART_NS8250_EARLY_REG_IO_WIDTH=2
+options BOOTVERBOSE
+
+# Include SoC specific configuration
+include "std.arm64"
+include "std.dev"
+include "std.mediatek"
+
diff --git a/sys/arm64/conf/std.mediatek b/sys/arm64/conf/std.mediatek
new file mode 100644
--- /dev/null
+++ b/sys/arm64/conf/std.mediatek
@@ -0,0 +1,10 @@
+options SOC_MEDIATEK
+
+device uart_ns8250
+
+# GPIO / PINCTRL
+device mt7622_pinctrl
+
+options FDT
+# DTBs
+makeoptions MODULES_EXTRA+="dtb/mediatek"
\ No newline at end of file
diff --git a/sys/arm64/mediatek/mdtk_clk.h b/sys/arm64/mediatek/mdtk_clk.h
new file mode 100644
--- /dev/null
+++ b/sys/arm64/mediatek/mdtk_clk.h
@@ -0,0 +1,149 @@
+#ifndef __MDTK_CLK_H__
+#define __MDTK_CLK_H__
+
+/*
+ * Copyright (c) 2025 Martin Filla
+ * Copyright (c) 2025 Michal Meloun <mmel@FreeBSD.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+/* Parent list */
+#define PLIST(_name) static const char *_name[]
+
+/* Standard gate. */
+#define GATE(_id, cname, plist, o, s) \
+{ \
+ .clkdef.id = _id, \
+ .clkdef.name = cname, \
+ .clkdef.parent_names = (const char *[]){plist}, \
+ .clkdef.parent_cnt = 1, \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ .offset = o, \
+ .shift = s, \
+ .mask = 1, \
+ .on_value = 1, \
+ .off_value = 0, \
+}
+
+/* Inverter gate. */
+#define I_GATE(_id, cname, plist, o, s) \
+{ \
+ .clkdef.id = _id, \
+ .clkdef.name = cname, \
+ .clkdef.parent_names = (const char *[]){plist}, \
+ .clkdef.parent_cnt = 1, \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ .offset = o, \
+ .shift = s, \
+ .mask = 1, \
+ .on_value = 0, \
+ .off_value = 1, \
+}
+
+/* Fixed rate clock. */
+#define FRATE(_id, _name, _freq) \
+{ \
+ .clkdef.id = _id, \
+ .clkdef.name = _name, \
+ .clkdef.parent_cnt = 0, \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ .freq = _freq, \
+}
+
+/* Link. */
+#define LINK(_idx, _clkname, _pname) \
+{ \
+ .clkdef.id = _idx, \
+ .clkdef.name = _clkname, \
+ .clkdef.parent_name = _pname, \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS \
+}
+
+/* Fixed factor clock. */
+#define FFACT(_id, _name, _pname, _mult, _div) \
+{ \
+ .clkdef.id = _id, \
+ .clkdef.name = _name, \
+ .clkdef.parent_names = (const char *[]){_pname}, \
+ .clkdef.parent_cnt = 1, \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ .mult = _mult, \
+ .div = _div, \
+}
+
+/* Divided clock. */
+#define DIV(_id, _name, _pname, _reg, _shift, _width) \
+{ \
+ .clkdef.id = _id, \
+ .clkdef.name = _name, \
+ .clkdef.parent_names = (const char *[]){_pname}, \
+ .clkdef.parent_cnt = 1, \
+ .offset = _reg, \
+ .i_shift = _shift, \
+ .i_width = _width, \
+}
+
+/* Pure multiplexer. */
+#define MUX0(_id, cname, plists, _reg, _shift, _width) \
+{ \
+ .clkdef.id = _id, \
+ .clkdef.name = cname, \
+ .clkdef.parent_names = plists, \
+ .clkdef.parent_cnt = nitems(plists), \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ .offset = _reg, \
+ .shift = _shift, \
+ .width = _width, \
+}
+
+/* Inverter gate. */
+#define I_GATE(_id, cname, plist, o, s) \
+{ \
+ .clkdef.id = _id, \
+ .clkdef.name = cname, \
+ .clkdef.parent_names = (const char *[]){plist}, \
+ .clkdef.parent_cnt = 1, \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ .offset = o, \
+ .shift = s, \
+ .mask = 1, \
+ .on_value = 0, \
+ .off_value = 1, \
+}
+
+struct mdtk_clk_def {
+ struct clk_link_def *linked_def;
+ struct clk_fixed_def *fixed_def;
+ struct clk_mux_def *muxes_def;
+ struct clk_gate_def *gates_def;
+ struct clk_div_def *dived_def;
+ int num_linked;
+ int num_fixed;
+ int num_muxes;
+ int num_gates;
+ int num_dived;
+};
+
+struct mdtk_clk_softc {
+ device_t dev;
+ struct resource *mem_res;
+ struct mtx mtx;
+ struct clkdom *clkdom;
+ struct syscon *syscon;
+};
+
+int mdtk_clkdev_read_4(device_t dev, bus_addr_t addr, uint32_t *val);
+
+int mdtk_clkdev_write_4(device_t dev, bus_addr_t addr, uint32_t val);
+
+int mdtk_clkdev_modify_4(device_t dev, bus_addr_t addr, uint32_t clear_mask,
+ uint32_t set_mask);
+
+void mdtk_clkdev_device_lock(device_t dev);
+
+void mdtk_clkdev_device_unlock(device_t dev);
+
+void mdtk_register_clocks(device_t dev, struct mdtk_clk_def *cldef);
+int mdtk_hwreset_by_idx(struct mdtk_clk_softc *sc, intptr_t idx, bool reset);
+#endif
diff --git a/sys/arm64/mediatek/mdtk_clk.c b/sys/arm64/mediatek/mdtk_clk.c
new file mode 100644
--- /dev/null
+++ b/sys/arm64/mediatek/mdtk_clk.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2025 Martin Filla
+ * Copyright (c) 2025 Michal Meloun <mmel@FreeBSD.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+#include <dev/fdt/simplebus.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dt-bindings/clock/mt7622-clk.h>
+#include <dev/clk/clk_fixed.h>
+#include <dev/clk/clk_div.h>
+#include <dev/clk/clk_mux.h>
+#include <dev/clk/clk_gate.h>
+#include <dev/clk/clk_link.h>
+
+#include <arm64/mediatek/mdtk_clk.h>
+
+static void
+init_fixeds(struct mdtk_clk_softc *sc, struct clk_fixed_def *clks,
+ int nclks) {
+ int i, rv;
+
+ for (i = 0; i < nclks; i++) {
+ rv = clknode_fixed_register(sc->clkdom, clks + i);
+ if (rv != 0)
+ panic("clknode_fixed_register failed");
+ }
+
+}
+
+static void
+init_linked(struct mdtk_clk_softc *sc, struct clk_link_def *clks,
+ int nclks) {
+ for (int i = 0; i < nclks; i++) {
+ int rv = clknode_link_register(sc->clkdom, clks + i);
+ if (rv != 0)
+ panic("clknode_link_register failed");
+ }
+
+}
+
+static void
+init_muxes(struct mdtk_clk_softc *sc, struct clk_mux_def *clks, int nclks) {
+ int i, rv;
+
+ for (i = 0; i < nclks; i++) {
+ rv = clknode_mux_register(sc->clkdom, clks + i);
+ if (rv != 0)
+ panic("clknode_mux_register failed");
+ }
+}
+
+static void
+init_gates(struct mdtk_clk_softc *sc, struct clk_gate_def *clks, int nclks) {
+ int i, rv;
+
+ for (i = 0; i < nclks; i++) {
+ rv = clknode_gate_register(sc->clkdom, clks + i);
+ if (rv != 0)
+ panic("clknode_gate_register failed");
+ }
+}
+
+static void
+init_div(struct mdtk_clk_softc *sc, struct clk_div_def *clks, int nclks) {
+ int i, rv;
+
+ for (i = 0; i < nclks; i++) {
+ rv = clknode_div_register(sc->clkdom, clks + i);
+ if (rv != 0)
+ panic("clknode_div_register failed");
+ }
+}
+
+int
+mdtk_clkdev_read_4(device_t dev, bus_addr_t addr, uint32_t *val) {
+ struct mdtk_clk_softc *sc;
+
+ sc = device_get_softc(dev);
+ *val = bus_read_4(sc->mem_res, addr);
+ return (0);
+}
+
+int
+mdtk_clkdev_write_4(device_t dev, bus_addr_t addr, uint32_t val) {
+ struct mdtk_clk_softc *sc;
+
+ sc = device_get_softc(dev);
+ bus_write_4(sc->mem_res, addr, val);
+ return (0);
+}
+
+int
+mdtk_clkdev_modify_4(device_t dev, bus_addr_t addr, uint32_t clear_mask,
+ uint32_t set_mask) {
+ struct mdtk_clk_softc *sc;
+ uint32_t reg;
+
+ sc = device_get_softc(dev);
+ reg = bus_read_4(sc->mem_res, addr);
+ reg &= ~clear_mask;
+ reg |= set_mask;
+ bus_write_4(sc->mem_res, addr, reg);
+ return (0);
+}
+
+void
+mdtk_clkdev_device_lock(device_t dev) {
+ struct mdtk_clk_softc *sc;
+
+ sc = device_get_softc(dev);
+ mtx_lock(&sc->mtx);
+}
+
+void
+mdtk_clkdev_device_unlock(device_t dev) {
+ struct mdtk_clk_softc *sc;
+
+ sc = device_get_softc(dev);
+ mtx_unlock(&sc->mtx);
+}
+
+void
+mdtk_register_clocks(device_t dev, struct mdtk_clk_def *cldef) {
+ struct mdtk_clk_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->clkdom = clkdom_create(dev);
+ if (sc->clkdom == NULL)
+ panic("clkdom == NULL");
+
+ init_fixeds(sc, cldef->fixed_def, cldef->num_fixed);
+ init_linked(sc, cldef->linked_def, cldef->num_linked);
+ init_muxes(sc, cldef->muxes_def, cldef->num_muxes);
+ init_gates(sc, cldef->gates_def, cldef->num_gates);
+ init_div(sc, cldef->dived_def, cldef->num_dived);
+
+ clkdom_finit(sc->clkdom);
+ if (bootverbose)
+ clkdom_dump(sc->clkdom);
+}
+
+int
+mdtk_hwreset_by_idx(struct mdtk_clk_softc *sc, intptr_t idx, bool reset) {
+ device_printf(sc->dev, "idx %ld, reset %d\n", idx, reset);
+ return (0);
+}
\ No newline at end of file
diff --git a/sys/arm64/mediatek/mt7622_clk_audio.c b/sys/arm64/mediatek/mt7622_clk_audio.c
new file mode 100644
--- /dev/null
+++ b/sys/arm64/mediatek/mt7622_clk_audio.c
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2025 Martin Filla
+ * Copyright (c) 2025 Michal Meloun <mmel@FreeBSD.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+#include <dev/fdt/simplebus.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/syscon/syscon.h>
+#include <dt-bindings/clock/mt7622-clk.h>
+#include <dev/clk/clk_gate.h>
+#include <dev/hwreset/hwreset.h>
+#include "syscon_if.h"
+#include "clkdev_if.h"
+#include "hwreset_if.h"
+#include "mdtk_clk.h"
+
+
+static struct ofw_compat_data compat_data[] = {
+ {"mediatek,mt7622-audsys", 1},
+ {NULL, 0},
+};
+
+static struct clk_gate_def gates_clk[] = {
+ /* AUDIO0 */
+ GATE(CLK_AUDIO_AFE, "audio_afe", "rtc", 0x0, 2),
+ GATE(CLK_AUDIO_HDMI, "audio_hdmi", "apll1_ck_sel", 0x0, 20),
+ GATE(CLK_AUDIO_SPDF, "audio_spdf", "apll1_ck_sel", 0x0, 21),
+ GATE(CLK_AUDIO_APLL, "audio_apll", "apll1_ck_sel", 0x0, 23),
+ /* AUDIO1 */
+ GATE(CLK_AUDIO_I2SIN1, "audio_i2sin1", "a1sys_hp_sel", 0x10, 0),
+ GATE(CLK_AUDIO_I2SIN2, "audio_i2sin2", "a1sys_hp_sel", 0x10, 1),
+ GATE(CLK_AUDIO_I2SIN3, "audio_i2sin3", "a1sys_hp_sel", 0x10, 2),
+ GATE(CLK_AUDIO_I2SIN4, "audio_i2sin4", "a1sys_hp_sel", 0x10, 3),
+ GATE(CLK_AUDIO_I2SO1, "audio_i2so1", "a1sys_hp_sel", 0x10, 6),
+ GATE(CLK_AUDIO_I2SO2, "audio_i2so2", "a1sys_hp_sel", 0x10, 7),
+ GATE(CLK_AUDIO_I2SO3, "audio_i2so3", "a1sys_hp_sel", 0x10, 8),
+ GATE(CLK_AUDIO_I2SO4, "audio_i2so4", "a1sys_hp_sel", 0x10, 9),
+ GATE(CLK_AUDIO_ASRCI1, "audio_asrci1", "asm_h_sel", 0x10, 12),
+ GATE(CLK_AUDIO_ASRCI2, "audio_asrci2", "asm_h_sel", 0x10, 13),
+ GATE(CLK_AUDIO_ASRCO1, "audio_asrco1", "asm_h_sel", 0x10, 14),
+ GATE(CLK_AUDIO_ASRCO2, "audio_asrco2", "asm_h_sel", 0x10, 15),
+ GATE(CLK_AUDIO_INTDIR, "audio_intdir", "intdir_sel", 0x10, 20),
+ GATE(CLK_AUDIO_A1SYS, "audio_a1sys", "a1sys_hp_sel", 0x10, 21),
+ GATE(CLK_AUDIO_A2SYS, "audio_a2sys", "a2sys_hp_sel", 0x10, 22),
+ GATE(CLK_AUDIO_AFE_CONN, "audio_afe_conn", "a1sys_hp_sel", 0x10, 23),
+ /* AUDIO2 */
+ GATE(CLK_AUDIO_UL1, "audio_ul1", "a1sys_hp_sel", 0x14, 0),
+ GATE(CLK_AUDIO_UL2, "audio_ul2", "a1sys_hp_sel", 0x14, 1),
+ GATE(CLK_AUDIO_UL3, "audio_ul3", "a1sys_hp_sel", 0x14, 2),
+ GATE(CLK_AUDIO_UL4, "audio_ul4", "a1sys_hp_sel", 0x14, 3),
+ GATE(CLK_AUDIO_UL5, "audio_ul5", "a1sys_hp_sel", 0x14, 4),
+ GATE(CLK_AUDIO_UL6, "audio_ul6", "a1sys_hp_sel", 0x14, 5),
+ GATE(CLK_AUDIO_DL1, "audio_dl1", "a1sys_hp_sel", 0x14, 6),
+ GATE(CLK_AUDIO_DL2, "audio_dl2", "a1sys_hp_sel", 0x14, 7),
+ GATE(CLK_AUDIO_DL3, "audio_dl3", "a1sys_hp_sel", 0x14, 8),
+ GATE(CLK_AUDIO_DL4, "audio_dl4", "a1sys_hp_sel", 0x14, 9),
+ GATE(CLK_AUDIO_DL5, "audio_dl5", "a1sys_hp_sel", 0x14, 10),
+ GATE(CLK_AUDIO_DL6, "audio_dl6", "a1sys_hp_sel", 0x14, 11),
+ GATE(CLK_AUDIO_DLMCH, "audio_dlmch", "a1sys_hp_sel", 0x14, 12),
+ GATE(CLK_AUDIO_ARB1, "audio_arb1", "a1sys_hp_sel", 0x14, 13),
+ GATE(CLK_AUDIO_AWB, "audio_awb", "a1sys_hp_sel", 0x14, 14),
+ GATE(CLK_AUDIO_AWB2, "audio_awb2", "a1sys_hp_sel", 0x14, 15),
+ GATE(CLK_AUDIO_DAI, "audio_dai", "a1sys_hp_sel", 0x14, 16),
+ GATE(CLK_AUDIO_MOD, "audio_mod", "a1sys_hp_sel", 0x14, 17),
+ /* AUDIO3 */
+ GATE(CLK_AUDIO_ASRCI3, "audio_asrci3", "asm_h_sel", 0x634, 2),
+ GATE(CLK_AUDIO_ASRCI4, "audio_asrci4", "asm_h_sel", 0x634, 3),
+ GATE(CLK_AUDIO_ASRCO3, "audio_asrco3", "asm_h_sel", 0x634, 6),
+ GATE(CLK_AUDIO_ASRCO4, "audio_asrco4", "asm_h_sel", 0x634, 7),
+ GATE(CLK_AUDIO_MEM_ASRC1, "audio_mem_asrc1", "asm_h_sel", 0x634, 10),
+ GATE(CLK_AUDIO_MEM_ASRC2, "audio_mem_asrc2", "asm_h_sel", 0x634, 11),
+ GATE(CLK_AUDIO_MEM_ASRC3, "audio_mem_asrc3", "asm_h_sel", 0x634, 12),
+ GATE(CLK_AUDIO_MEM_ASRC4, "audio_mem_asrc4", "asm_h_sel", 0x634, 13),
+ GATE(CLK_AUDIO_MEM_ASRC5, "audio_mem_asrc5", "asm_h_sel", 0x634, 14),
+};
+
+static struct mdtk_clk_def clk_def = {
+ .gates_def = gates_clk,
+ .num_gates = nitems(gates_clk),
+};
+
+static int
+audio_clk_detach(device_t dev) {
+ device_printf(dev, "Error: Clock driver cannot be detached\n");
+ return (EBUSY);
+}
+
+static int
+audio_clk_probe(device_t dev) {
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) {
+ device_set_desc(dev, "Mediatek mt7622 audio clocks");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+audio_clk_attach(device_t dev) {
+ struct mdtk_clk_softc *sc = device_get_softc(dev);
+ int rid = 0;
+
+ sc->dev = dev;
+
+ mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+
+ if (ofw_bus_is_compatible(dev, "syscon")) {
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev,
+ "Cannot allocate memory resource\n");
+ return (ENXIO);
+ }
+
+ sc->syscon = syscon_create_ofw_node(dev,
+ &syscon_class, ofw_bus_get_node(dev));
+ if (sc->syscon == NULL) {
+ device_printf(dev,
+ "Failed to create/register syscon\n");
+ return (ENXIO);
+ }
+ }
+
+ mdtk_register_clocks(dev, &clk_def);
+ return (0);
+}
+
+static int
+audio_clk_hwreset_assert(device_t dev, intptr_t idx, bool value) {
+ struct mdtk_clk_softc *sc = device_get_softc(dev);
+ uint32_t mask, reset_reg;
+
+ CLKDEV_DEVICE_LOCK(sc->dev);
+ KASSERT((idx > 0 && idx < 32), ("%s: idx out of range", __func__));
+
+
+ mask = 1 << (idx % 32);
+ reset_reg = (idx / 32) * 4;
+
+ CLKDEV_MODIFY_4(sc->dev, reset_reg, mask, value ? mask : 0);
+ CLKDEV_DEVICE_UNLOCK(sc->dev);
+
+ return (0);
+}
+
+static int
+audio_clk_syscon_get_handle(device_t dev, struct syscon **syscon) {
+ struct mdtk_clk_softc *sc;
+
+ sc = device_get_softc(dev);
+ *syscon = sc->syscon;
+ if (*syscon == NULL) {
+ return (ENODEV);
+ }
+
+ return (0);
+}
+
+static void
+audio_clk_syscon_lock(device_t dev) {
+ struct mdtk_clk_softc *sc;
+
+ sc = device_get_softc(dev);
+ mtx_lock(&sc->mtx);
+}
+
+static void
+audio_clk_syscon_unlock(device_t dev) {
+ struct mdtk_clk_softc *sc;
+
+ sc = device_get_softc(dev);
+ mtx_unlock(&sc->mtx);
+}
+
+static device_method_t mt7622_audio_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, audio_clk_probe),
+ DEVMETHOD(device_attach, audio_clk_attach),
+ DEVMETHOD(device_detach, audio_clk_detach),
+
+ /* Clkdev interface*/
+ DEVMETHOD(clkdev_read_4, mdtk_clkdev_read_4),
+ DEVMETHOD(clkdev_write_4, mdtk_clkdev_write_4),
+ DEVMETHOD(clkdev_modify_4, mdtk_clkdev_modify_4),
+ DEVMETHOD(clkdev_device_lock, mdtk_clkdev_device_lock),
+ DEVMETHOD(clkdev_device_unlock, mdtk_clkdev_device_unlock),
+
+ DEVMETHOD(hwreset_assert, audio_clk_hwreset_assert),
+
+ /* Syscon interface */
+ DEVMETHOD(syscon_get_handle, audio_clk_syscon_get_handle),
+ DEVMETHOD(syscon_device_lock, audio_clk_syscon_lock),
+ DEVMETHOD(syscon_device_unlock, audio_clk_syscon_unlock),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_1(mt7622_audio, mt7622_audio_driver, mt7622_audio_methods,
+sizeof(struct mdtk_clk_softc), syscon_class);
+
+EARLY_DRIVER_MODULE(mt7622_audio, simplebus, mt7622_audio_driver, NULL, NULL,
+ BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE + 4);
diff --git a/sys/arm64/mediatek/mt7622_clk_eth.c b/sys/arm64/mediatek/mt7622_clk_eth.c
new file mode 100644
--- /dev/null
+++ b/sys/arm64/mediatek/mt7622_clk_eth.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2025 Martin Filla
+ * Copyright (c) 2025 Michal Meloun <mmel@FreeBSD.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+#include <dev/fdt/simplebus.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/syscon/syscon.h>
+#include <dt-bindings/clock/mt7622-clk.h>
+#include <dev/clk/clk_gate.h>
+#include <dev/hwreset/hwreset.h>
+#include "syscon_if.h"
+#include "clkdev_if.h"
+#include "hwreset_if.h"
+#include "mdtk_clk.h"
+
+static struct ofw_compat_data compat_data[] = {
+ {"mediatek,mt7622-ethsys", 1},
+ {NULL, 0},
+};
+
+static struct clk_gate_def gates_clk[] = {
+ /* eth */
+ GATE(CLK_ETH_HSDMA_EN, "eth_hsdma_en", "eth_sel", 0x30, 5),
+ GATE(CLK_ETH_ESW_EN, "eth_esw_en", "eth_500m", 0x30, 6),
+ GATE(CLK_ETH_GP2_EN, "eth_gp2_en", "txclk_src_pre", 0x30, 7),
+ GATE(CLK_ETH_GP1_EN, "eth_gp1_en", "txclk_src_pre", 0x30, 8),
+ GATE(CLK_ETH_GP0_EN, "eth_gp0_en", "txclk_src_pre", 0x30, 9),
+};
+
+static struct mdtk_clk_def clk_def = {
+ .gates_def = gates_clk,
+ .num_gates = nitems(gates_clk),
+};
+
+static int
+eth_clk_detach(device_t dev) {
+ device_printf(dev, "Error: Clock driver cannot be detached\n");
+ return (EBUSY);
+}
+
+static int
+eth_clk_probe(device_t dev) {
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) {
+ device_set_desc(dev, "Mediatek mt7622 ethernet clocks");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+eth_clk_attach(device_t dev) {
+ struct mdtk_clk_softc *sc = device_get_softc(dev);
+ int rid = 0;
+
+ sc->dev = dev;
+
+ mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+
+ if (ofw_bus_is_compatible(dev, "syscon")) {
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev,
+ "Cannot allocate memory resource\n");
+ return (ENXIO);
+ }
+
+ sc->syscon = syscon_create_ofw_node(dev,
+ &syscon_class, ofw_bus_get_node(dev));
+ if (sc->syscon == NULL) {
+ device_printf(dev,
+ "Failed to create/register syscon\n");
+ return (ENXIO);
+ }
+ }
+
+ mdtk_register_clocks(dev, &clk_def);
+ return (0);
+}
+
+static int
+eth_clk_syscon_get_handle(device_t dev, struct syscon **syscon) {
+ struct mdtk_clk_softc *sc;
+
+ sc = device_get_softc(dev);
+ *syscon = sc->syscon;
+ if (*syscon == NULL) {
+ return (ENODEV);
+ }
+
+ return (0);
+}
+
+static void
+eth_clk_syscon_lock(device_t dev) {
+ struct mdtk_clk_softc *sc;
+
+ sc = device_get_softc(dev);
+ mtx_lock(&sc->mtx);
+}
+
+static void
+eth_clk_syscon_unlock(device_t dev) {
+ struct mdtk_clk_softc *sc;
+
+ sc = device_get_softc(dev);
+ mtx_unlock(&sc->mtx);
+}
+
+static device_method_t mt7622_eth_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, eth_clk_probe),
+ DEVMETHOD(device_attach, eth_clk_attach),
+ DEVMETHOD(device_detach, eth_clk_detach),
+
+ /* Clkdev interface*/
+ DEVMETHOD(clkdev_read_4, mdtk_clkdev_read_4),
+ DEVMETHOD(clkdev_write_4, mdtk_clkdev_write_4),
+ DEVMETHOD(clkdev_modify_4, mdtk_clkdev_modify_4),
+ DEVMETHOD(clkdev_device_lock, mdtk_clkdev_device_lock),
+ DEVMETHOD(clkdev_device_unlock, mdtk_clkdev_device_unlock),
+
+ /* Syscon interface */
+ DEVMETHOD(syscon_get_handle, eth_clk_syscon_get_handle),
+ DEVMETHOD(syscon_device_lock, eth_clk_syscon_lock),
+ DEVMETHOD(syscon_device_unlock, eth_clk_syscon_unlock),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_1(mt7622_eth, mt7622_eth_driver, mt7622_eth_methods,
+sizeof(struct mdtk_clk_softc), syscon_class);
+
+EARLY_DRIVER_MODULE(mt7622_eth, simplebus, mt7622_eth_driver, NULL, NULL,
+ BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE + 5);
\ No newline at end of file
diff --git a/sys/arm64/mediatek/mt7622_clk_infracfg.c b/sys/arm64/mediatek/mt7622_clk_infracfg.c
new file mode 100644
--- /dev/null
+++ b/sys/arm64/mediatek/mt7622_clk_infracfg.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2025 Martin Filla
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+#include <dev/fdt/simplebus.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/syscon/syscon.h>
+#include <dt-bindings/clock/mt7622-clk.h>
+#include <dev/clk/clk_mux.h>
+#include <dev/clk/clk_gate.h>
+#include <dev/hwreset/hwreset.h>
+#include "syscon_if.h"
+#include "clkdev_if.h"
+#include "hwreset_if.h"
+#include "mdtk_clk.h"
+
+static struct ofw_compat_data compat_data[] = {
+ {"mediatek,mt7622-infracfg", 1},
+ {NULL, 0},
+};
+
+PLIST(infra_mux1_parents) = {
+ "clkxtal",
+ "armpll",
+ //"main_core_en",
+ "armpll"
+};
+
+static struct clk_gate_def gates_clk[] = {
+ GATE(CLK_INFRA_DBGCLK_PD, "infra_dbgclk_pd", "axi_sel", 0x44, 0),
+ GATE(CLK_INFRA_TRNG, "trng_ck", "axi_sel", 0x44, 2),
+ GATE(CLK_INFRA_AUDIO_PD, "infra_audio_pd", "aud_intbus_sel", 0x44, 5),
+ //GATE(CLK_INFRA_IRRX_PD, "infra_irrx_pd", "irrx_sel", 0x44, 16),
+ GATE(CLK_INFRA_APXGPT_PD, "infra_apxgpt_pd", "f10m_ref_sel", 0x44, 18),
+ GATE(CLK_INFRA_PMIC_PD, "infra_pmic_pd", "pmicspi_sel", 0x44, 22),
+};
+
+static struct clk_mux_def muxes_clk[] = {
+ MUX0(CLK_INFRA_MUX1_SEL, "infra_mux1_sel", infra_mux1_parents, 0x000, 2, 2),
+};
+
+static struct mdtk_clk_def clk_def = {
+ .gates_def = gates_clk,
+ .num_gates = nitems(gates_clk),
+ .muxes_def = muxes_clk,
+ .num_muxes = nitems(muxes_clk),
+};
+
+static int
+infracfg_clk_detach(device_t dev) {
+ device_printf(dev, "Error: Clock driver cannot be detached\n");
+ return (EBUSY);
+}
+
+static int
+infracfg_clk_probe(device_t dev) {
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) {
+ device_set_desc(dev, "Mediatek infracfg clocks");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+infracfg_clk_attach(device_t dev) {
+ struct mdtk_clk_softc *sc = device_get_softc(dev);
+ int rid = 0;
+
+ sc->dev = dev;
+
+ mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+
+ if (ofw_bus_is_compatible(dev, "syscon")) {
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev,
+ "Cannot allocate memory resource\n");
+ return (ENXIO);
+ }
+
+ sc->syscon = syscon_create_ofw_node(dev,
+ &syscon_class, ofw_bus_get_node(dev));
+ if (sc->syscon == NULL) {
+ device_printf(dev,
+ "Failed to create/register syscon\n");
+ return (ENXIO);
+ }
+ }
+
+ mdtk_register_clocks(dev, &clk_def);
+ return (0);
+}
+
+static int
+infracfg_clk_hwreset_assert(device_t dev, intptr_t idx, bool value) {
+ struct mdtk_clk_softc *sc = device_get_softc(dev);
+ uint32_t mask, reset_reg;
+
+ CLKDEV_DEVICE_LOCK(sc->dev);
+ KASSERT((idx > 0 && idx < 32), ("%s: idx out of range", __func__));
+
+
+ mask = 1 << (idx % 32);
+ reset_reg = (idx / 32) * 4;
+
+ CLKDEV_MODIFY_4(sc->dev, reset_reg, mask, value ? mask : 0);
+ CLKDEV_DEVICE_UNLOCK(sc->dev);
+
+ return (0);
+}
+
+static int
+infracfg_clk_syscon_get_handle(device_t dev, struct syscon **syscon) {
+ struct mdtk_clk_softc *sc;
+
+ sc = device_get_softc(dev);
+ *syscon = sc->syscon;
+ if (*syscon == NULL) {
+ return (ENODEV);
+ }
+
+ return (0);
+}
+
+static void
+infracfg_clk_syscon_lock(device_t dev) {
+ struct mdtk_clk_softc *sc;
+
+ sc = device_get_softc(dev);
+ mtx_lock(&sc->mtx);
+}
+
+static void
+infracfg_clk_syscon_unlock(device_t dev) {
+ struct mdtk_clk_softc *sc;
+
+ sc = device_get_softc(dev);
+ mtx_unlock(&sc->mtx);
+}
+
+static device_method_t mt7622_infracfg_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, infracfg_clk_probe),
+ DEVMETHOD(device_attach, infracfg_clk_attach),
+ DEVMETHOD(device_detach, infracfg_clk_detach),
+
+ /* Clkdev interface*/
+ DEVMETHOD(clkdev_read_4, mdtk_clkdev_read_4),
+ DEVMETHOD(clkdev_write_4, mdtk_clkdev_write_4),
+ DEVMETHOD(clkdev_modify_4, mdtk_clkdev_modify_4),
+ DEVMETHOD(clkdev_device_lock, mdtk_clkdev_device_lock),
+ DEVMETHOD(clkdev_device_unlock, mdtk_clkdev_device_unlock),
+
+ DEVMETHOD(hwreset_assert, infracfg_clk_hwreset_assert),
+
+ /* Syscon interface */
+ DEVMETHOD(syscon_get_handle, infracfg_clk_syscon_get_handle),
+ DEVMETHOD(syscon_device_lock, infracfg_clk_syscon_lock),
+ DEVMETHOD(syscon_device_unlock, infracfg_clk_syscon_unlock),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_1(mt7622_infracfg, mt7622_infracfg_driver, mt7622_infracfg_methods,
+sizeof(struct mdtk_clk_softc), syscon_class);
+
+EARLY_DRIVER_MODULE(mt7622_infracfg, simplebus, mt7622_infracfg_driver, NULL, NULL,
+ BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE + 4);
\ No newline at end of file
diff --git a/sys/arm64/mediatek/mt7622_clk_pciesys.c b/sys/arm64/mediatek/mt7622_clk_pciesys.c
new file mode 100644
--- /dev/null
+++ b/sys/arm64/mediatek/mt7622_clk_pciesys.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2025 Martin Filla
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+#include <dev/fdt/simplebus.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dt-bindings/clock/mt7622-clk.h>
+
+#include <dev/clk/clk_fixed.h>
+#include <dev/clk/clk_div.h>
+#include <dev/clk/clk_mux.h>
+#include <dev/clk/clk_gate.h>
+#include <dev/clk/clk_link.h>
+#include <arm64/mediatek/mdtk_clk.h>
+#include "clkdev_if.h"
+#include "hwreset_if.h"
+#include "mdtk_clk.h"
+
+static struct ofw_compat_data compat_data[] = {
+ {"mediatek,mt7622-pciesys", 1},
+ {NULL, 0},
+};
+
+static struct clk_gate_def gates_pcie_clk[] = {
+ GATE(CLK_PCIE_P1_AUX_EN, "pcie_p1_aux_en", "p1_1mhz", 0x30, 12),
+ GATE(CLK_PCIE_P1_OBFF_EN, "pcie_p1_obff_en", "free_run_4mhz", 0x30, 13),
+ GATE(CLK_PCIE_P1_AHB_EN, "pcie_p1_ahb_en", "axi_sel", 0x30, 14),
+ GATE(CLK_PCIE_P1_AXI_EN, "pcie_p1_axi_en", "hif_sel", 0x30, 15),
+ GATE(CLK_PCIE_P1_MAC_EN, "pcie_p1_mac_en", "pcie1_mac_en", 0x30, 16),
+ GATE(CLK_PCIE_P1_PIPE_EN, "pcie_p1_pipe_en", "pcie1_pipe_en", 0x30, 17),
+ GATE(CLK_PCIE_P0_AUX_EN, "pcie_p0_aux_en", "p0_1mhz", 0x30, 18),
+ GATE(CLK_PCIE_P0_OBFF_EN, "pcie_p0_obff_en", "free_run_4mhz", 0x30, 19),
+ GATE(CLK_PCIE_P0_AHB_EN, "pcie_p0_ahb_en", "axi_sel", 0x30, 20),
+ GATE(CLK_PCIE_P0_AXI_EN, "pcie_p0_axi_en", "hif_sel", 0x30, 21),
+ GATE(CLK_PCIE_P0_MAC_EN, "pcie_p0_mac_en", "pcie0_mac_en", 0x30, 22),
+ GATE(CLK_PCIE_P0_PIPE_EN, "pcie_p0_pipe_en", "pcie0_pipe_en", 0x30, 23),
+ GATE(CLK_SATA_AHB_EN, "sata_ahb_en", "axi_sel", 0x30, 26),
+ GATE(CLK_SATA_AXI_EN, "sata_axi_en", "hif_sel", 0x30, 27),
+ GATE(CLK_SATA_ASIC_EN, "sata_asic_en", "sata_asic", 0x30, 28),
+ GATE(CLK_SATA_RBC_EN, "sata_rbc_en", "sata_rbc", 0x30, 29),
+ GATE(CLK_SATA_PM_EN, "sata_pm_en", "univpll2_d4", 0x30, 30),
+};
+
+static struct mdtk_clk_def clk_pcie_def = {
+ .linked_def = NULL,
+ .num_linked = 0,
+ .fixed_def = NULL,
+ .num_fixed = 0,
+ .gates_def = gates_pcie_clk,
+ .num_gates = nitems(gates_pcie_clk),
+ .muxes_def = NULL,
+ .num_muxes = 0,
+};
+
+static int
+mt7622_pciesys_clk_detach(device_t dev) {
+ device_printf(dev, "Error: Clock driver cannot be detached\n");
+ return (EBUSY);
+}
+
+static int
+mt7622_pciesys_clk_probe(device_t dev) {
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) {
+ device_set_desc(dev, "Mediatek mt7622 pciesys clocks");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+mt7622_pciesys_clk_attach(device_t dev) {
+ struct mdtk_clk_softc *sc;
+ sc = device_get_softc(dev);
+ int rid;
+
+ sc->dev = dev;
+
+ mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (!sc->mem_res) {
+ device_printf(dev, "cannot allocate memory resource\n");
+ return (ENXIO);
+ }
+
+ mdtk_register_clocks(dev, &clk_pcie_def);
+
+ return (0);
+}
+
+static int
+mt7622_pciesys_clk_hwreset_assert(device_t dev, intptr_t idx, bool value) {
+ struct mdtk_clk_softc *sc;
+ sc = device_get_softc(dev);
+ uint32_t mask, reset_reg;
+
+ CLKDEV_DEVICE_LOCK(sc->dev);
+ KASSERT((idx > 0 && idx < 32), ("%s: idx out of range", __func__));
+
+
+ mask = 1 << (idx % 32);
+ reset_reg = (idx / 32) * 4;
+
+ CLKDEV_MODIFY_4(sc->dev, reset_reg, mask, value ? mask : 0);
+ CLKDEV_DEVICE_UNLOCK(sc->dev);
+
+ return (0);
+}
+
+static device_method_t mt7622_pciesys_clk_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, mt7622_pciesys_clk_probe),
+ DEVMETHOD(device_attach, mt7622_pciesys_clk_attach),
+ DEVMETHOD(device_detach, mt7622_pciesys_clk_detach),
+
+ /* Clkdev interface*/
+ DEVMETHOD(clkdev_read_4, mdtk_clkdev_read_4),
+ DEVMETHOD(clkdev_write_4, mdtk_clkdev_write_4),
+ DEVMETHOD(clkdev_modify_4, mdtk_clkdev_modify_4),
+ DEVMETHOD(clkdev_device_lock, mdtk_clkdev_device_lock),
+ DEVMETHOD(clkdev_device_unlock, mdtk_clkdev_device_unlock),
+
+ DEVMETHOD(hwreset_assert, mt7622_pciesys_clk_hwreset_assert),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(mt7622_pciesys, mt7622_pciesys_driver, mt7622_pciesys_clk_methods,
+sizeof(struct mdtk_clk_softc));
+
+EARLY_DRIVER_MODULE(mt7622_pciesys, simplebus, mt7622_pciesys_driver, NULL, NULL,
+ BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE + 5);
diff --git a/sys/arm64/mediatek/mt7622_clk_pericfg.c b/sys/arm64/mediatek/mt7622_clk_pericfg.c
new file mode 100644
--- /dev/null
+++ b/sys/arm64/mediatek/mt7622_clk_pericfg.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2025 Martin Filla
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+#include <dev/fdt/simplebus.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/syscon/syscon.h>
+#include <dt-bindings/clock/mt7622-clk.h>
+#include <dev/clk/clk_mux.h>
+#include <dev/clk/clk_gate.h>
+#include <dev/hwreset/hwreset.h>
+#include "syscon_if.h"
+#include "clkdev_if.h"
+#include "hwreset_if.h"
+#include "mdtk_clk.h"
+
+#define PERICFG_CG0 0x10
+#define PERICFG_CG1 0x14
+
+static struct ofw_compat_data compat_data[] = {
+ {"mediatek,mt7622-pericfg", 1},
+ {NULL, 0},
+};
+
+PLIST(peribus_ck_parents) = {
+ "syspll1_d8",
+ "syspll1_d4"
+};
+
+static struct clk_gate_def gates_clk[] = {
+ GATE(CLK_PERI_THERM_PD, "peri_therm_pd", "axi_sel", PERICFG_CG0, 1),
+ GATE(CLK_PERI_PWM1_PD, "peri_pwm1_pd", "clkxtal", PERICFG_CG0, 2),
+ GATE(CLK_PERI_PWM2_PD, "peri_pwm2_pd", "clkxtal", PERICFG_CG0, 3),
+ GATE(CLK_PERI_PWM3_PD, "peri_pwm3_pd", "clkxtal", PERICFG_CG0, 4),
+ GATE(CLK_PERI_PWM4_PD, "peri_pwm4_pd", "clkxtal", PERICFG_CG0, 5),
+ GATE(CLK_PERI_PWM5_PD, "peri_pwm5_pd", "clkxtal", PERICFG_CG0, 6),
+ GATE(CLK_PERI_PWM6_PD, "peri_pwm6_pd", "clkxtal", PERICFG_CG0, 7),
+ GATE(CLK_PERI_PWM7_PD, "peri_pwm7_pd", "clkxtal", PERICFG_CG0, 8),
+ GATE(CLK_PERI_PWM_PD, "peri_pwm_pd", "clkxtal", PERICFG_CG0, 9),
+ GATE(CLK_PERI_AP_DMA_PD, "peri_ap_dma_pd", "axi_sel", PERICFG_CG0, 12),
+ GATE(CLK_PERI_MSDC30_0_PD, "peri_msdc30_0", "msdc30_0_sel", PERICFG_CG0, 13),
+ GATE(CLK_PERI_MSDC30_1_PD, "peri_msdc30_1", "msdc30_1_sel", PERICFG_CG0, 14),
+ GATE(CLK_PERI_UART0_PD, "peri_uart0_pd", "axi_sel", PERICFG_CG0, 17),
+ GATE(CLK_PERI_UART1_PD, "peri_uart1_pd", "axi_sel", PERICFG_CG0, 18),
+ GATE(CLK_PERI_UART2_PD, "peri_uart2_pd", "axi_sel", PERICFG_CG0, 19),
+ GATE(CLK_PERI_UART3_PD, "peri_uart3_pd", "axi_sel", PERICFG_CG0, 20),
+ GATE(CLK_PERI_UART4_PD, "peri_uart4_pd", "axi_sel", PERICFG_CG0, 21),
+ GATE(CLK_PERI_BTIF_PD, "peri_btif_pd", "axi_sel", PERICFG_CG0, 22),
+ GATE(CLK_PERI_I2C0_PD, "peri_i2c0_pd", "axi_sel", PERICFG_CG0, 23),
+ GATE(CLK_PERI_I2C1_PD, "peri_i2c1_pd", "axi_sel", PERICFG_CG0, 24),
+ GATE(CLK_PERI_I2C2_PD, "peri_i2c2_pd", "axi_sel", PERICFG_CG0, 25),
+ GATE(CLK_PERI_SPI1_PD, "peri_spi1_pd", "spi1_sel", PERICFG_CG0, 26),
+ GATE(CLK_PERI_AUXADC_PD, "peri_auxadc_pd", "clkxtal", PERICFG_CG0, 27),
+ GATE(CLK_PERI_SPI0_PD, "peri_spi0_pd", "spi0_sel", PERICFG_CG0, 28),
+ GATE(CLK_PERI_SNFI_PD, "peri_snfi_pd", "spinfi_infra_bclk_sel", PERICFG_CG0, 29),
+ GATE(CLK_PERI_NFI_PD, "peri_nfi_pd", "axi_sel", PERICFG_CG0, 30),
+ GATE(CLK_PERI_NFIECC_PD, "peri_nfiecc_pd", "axi_sel", PERICFG_CG0, 31),
+
+ GATE(CLK_PERI_FLASH_PD, "peri_flash_pd", "flash_sel", PERICFG_CG1, 1),
+ GATE(CLK_PERI_IRTX_PD, "peri_irtx_pd", "irtx_sel", PERICFG_CG1, 2),
+};
+
+static struct clk_mux_def muxes_clk[] = {
+ MUX0(0, "peribus_ck_sel_mux", peribus_ck_parents, 0x05C, 0, 1),
+};
+
+
+static struct mdtk_clk_def clk_def = {
+ .gates_def = gates_clk,
+ .num_gates = nitems(gates_clk),
+ .muxes_def = muxes_clk,
+ .num_muxes = nitems(muxes_clk),
+};
+
+static int
+pericfg_clk_detach(device_t dev) {
+ device_printf(dev, "Error: Clock driver cannot be detached\n");
+ return (EBUSY);
+}
+
+static int
+pericfg_clk_probe(device_t dev) {
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) {
+ device_set_desc(dev, "Mediatek pericfg clocks");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+pericfg_clk_attach(device_t dev) {
+ struct mdtk_clk_softc *sc = device_get_softc(dev);
+ int rid = 0;
+
+ sc->dev = dev;
+
+ if (ofw_bus_is_compatible(dev, "syscon")) {
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev,
+ "Cannot allocate memory resource\n");
+ return (ENXIO);
+ }
+
+ mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+ sc->syscon = syscon_create_ofw_node(dev,
+ &syscon_class, ofw_bus_get_node(dev));
+ if (sc->syscon == NULL) {
+ device_printf(dev,
+ "Failed to create/register syscon\n");
+ return (ENXIO);
+ }
+ }
+
+ mdtk_register_clocks(dev, &clk_def);
+ return (0);
+}
+
+static int
+pericfg_clk_hwreset_assert(device_t dev, intptr_t idx, bool value) {
+ struct mdtk_clk_softc *sc = device_get_softc(dev);
+ uint32_t mask, reset_reg;
+
+ CLKDEV_DEVICE_LOCK(sc->dev);
+ KASSERT((idx > 0 && idx < 32), ("%s: idx out of range", __func__));
+
+
+ mask = 1 << (idx % 32);
+ reset_reg = (idx / 32) * 4;
+
+ CLKDEV_MODIFY_4(sc->dev, reset_reg, mask, value ? mask : 0);
+ CLKDEV_DEVICE_UNLOCK(sc->dev);
+
+ return (0);
+}
+
+static int
+pericfg_clk_syscon_get_handle(device_t dev, struct syscon **syscon) {
+ struct mdtk_clk_softc *sc;
+
+ sc = device_get_softc(dev);
+ *syscon = sc->syscon;
+ if (*syscon == NULL) {
+ return (ENODEV);
+ }
+
+ return (0);
+}
+
+static void
+pericfg_clk_syscon_lock(device_t dev) {
+ struct mdtk_clk_softc *sc;
+
+ sc = device_get_softc(dev);
+ mtx_lock(&sc->mtx);
+}
+
+static void
+pericfg_clk_syscon_unlock(device_t dev) {
+ struct mdtk_clk_softc *sc;
+
+ sc = device_get_softc(dev);
+ mtx_unlock(&sc->mtx);
+}
+
+static device_method_t mdtk_mt7622_pericfg_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, pericfg_clk_probe),
+ DEVMETHOD(device_attach, pericfg_clk_attach),
+ DEVMETHOD(device_detach, pericfg_clk_detach),
+
+ /* Clkdev interface*/
+ DEVMETHOD(clkdev_read_4, mdtk_clkdev_read_4),
+ DEVMETHOD(clkdev_write_4, mdtk_clkdev_write_4),
+ DEVMETHOD(clkdev_modify_4, mdtk_clkdev_modify_4),
+ DEVMETHOD(clkdev_device_lock, mdtk_clkdev_device_lock),
+ DEVMETHOD(clkdev_device_unlock, mdtk_clkdev_device_unlock),
+
+ DEVMETHOD(hwreset_assert, pericfg_clk_hwreset_assert),
+
+ /* Syscon interface */
+ DEVMETHOD(syscon_get_handle, pericfg_clk_syscon_get_handle),
+ DEVMETHOD(syscon_device_lock, pericfg_clk_syscon_lock),
+ DEVMETHOD(syscon_device_unlock, pericfg_clk_syscon_unlock),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_1(mdtk_mt7622_pericfg, mdtk_mt7622_pericfg_driver, mdtk_mt7622_pericfg_methods,
+sizeof(struct mdtk_clk_softc), syscon_class);
+
+EARLY_DRIVER_MODULE(mdtk_mt7622_pericfg, simplebus, mdtk_mt7622_pericfg_driver, NULL, NULL,
+ BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE + 3);
+
diff --git a/sys/arm64/mediatek/mt7622_clk_sgmii.c b/sys/arm64/mediatek/mt7622_clk_sgmii.c
new file mode 100644
--- /dev/null
+++ b/sys/arm64/mediatek/mt7622_clk_sgmii.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2025 Martin Filla
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+#include <dev/fdt/simplebus.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/syscon/syscon.h>
+#include <dt-bindings/clock/mt7622-clk.h>
+#include <dev/clk/clk_gate.h>
+#include "syscon_if.h"
+#include "clkdev_if.h"
+#include "hwreset_if.h"
+#include "mdtk_clk.h"
+
+static struct ofw_compat_data compat_data[] = {
+ {"mediatek,mt7622-sgmiisys", 1},
+ {NULL, 0},
+};
+
+static struct clk_gate_def gates_clk[] = {
+ /* sgmii */
+ GATE(CLK_SGMII_TX250M_EN, "sgmii_tx250m_en", "ssusb_tx250m", 0xE4, 2),
+ GATE(CLK_SGMII_RX250M_EN, "sgmii_rx250m_en", "ssusb_eq_rx250m", 0xE4, 3),
+ GATE(CLK_SGMII_CDR_REF, "sgmii_cdr_ref", "ssusb_cdr_ref", 0xE4, 4),
+ GATE(CLK_SGMII_CDR_FB, "sgmii_cdr_fb", "ssusb_cdr_fb", 0xE4, 5),
+};
+
+static struct mdtk_clk_def clk_def = {
+ .gates_def = gates_clk,
+ .num_gates = nitems(gates_clk),
+};
+
+static int
+sgmii_clk_detach(device_t dev) {
+ device_printf(dev, "Error: Clock driver cannot be detached\n");
+ return (EBUSY);
+}
+
+static int
+sgmii_clk_probe(device_t dev) {
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) {
+ device_set_desc(dev, "Mediatek mt7622 sgmii clocks");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+sgmii_clk_attach(device_t dev) {
+ struct mdtk_clk_softc *sc = device_get_softc(dev);
+ int rid = 0;
+
+ sc->dev = dev;
+
+ mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+
+ if (ofw_bus_is_compatible(dev, "syscon")) {
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev,
+ "Cannot allocate memory resource\n");
+ return (ENXIO);
+ }
+
+ sc->syscon = syscon_create_ofw_node(dev,
+ &syscon_class, ofw_bus_get_node(dev));
+ if (sc->syscon == NULL) {
+ device_printf(dev,
+ "Failed to create/register syscon\n");
+ return (ENXIO);
+ }
+ }
+
+ mdtk_register_clocks(dev, &clk_def);
+ return (0);
+}
+
+static int
+sgmii_clk_syscon_get_handle(device_t dev, struct syscon **syscon) {
+ struct mdtk_clk_softc *sc;
+
+ sc = device_get_softc(dev);
+ *syscon = sc->syscon;
+ if (*syscon == NULL) {
+ return (ENODEV);
+ }
+
+ return (0);
+}
+
+static void
+sgmii_clk_syscon_lock(device_t dev) {
+ struct mdtk_clk_softc *sc;
+
+ sc = device_get_softc(dev);
+ mtx_lock(&sc->mtx);
+}
+
+static void
+sgmii_clk_syscon_unlock(device_t dev) {
+ struct mdtk_clk_softc *sc;
+
+ sc = device_get_softc(dev);
+ mtx_unlock(&sc->mtx);
+}
+
+static device_method_t mt7622_sgmii_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, sgmii_clk_probe),
+ DEVMETHOD(device_attach, sgmii_clk_attach),
+ DEVMETHOD(device_detach, sgmii_clk_detach),
+
+ /* Clkdev interface*/
+ DEVMETHOD(clkdev_read_4, mdtk_clkdev_read_4),
+ DEVMETHOD(clkdev_write_4, mdtk_clkdev_write_4),
+ DEVMETHOD(clkdev_modify_4, mdtk_clkdev_modify_4),
+ DEVMETHOD(clkdev_device_lock, mdtk_clkdev_device_lock),
+ DEVMETHOD(clkdev_device_unlock, mdtk_clkdev_device_unlock),
+
+ /* Syscon interface */
+ DEVMETHOD(syscon_get_handle, sgmii_clk_syscon_get_handle),
+ DEVMETHOD(syscon_device_lock, sgmii_clk_syscon_lock),
+ DEVMETHOD(syscon_device_unlock, sgmii_clk_syscon_unlock),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_1(mt7622_sgmii, mt7622_sgmii_driver, mt7622_sgmii_methods,
+sizeof(struct mdtk_clk_softc), syscon_class);
+
+EARLY_DRIVER_MODULE(mt7622_sgmii, simplebus, mt7622_sgmii_driver, NULL, NULL,
+ BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE + 5);
\ No newline at end of file
diff --git a/sys/arm64/mediatek/mt7622_clk_ssusbsys.c b/sys/arm64/mediatek/mt7622_clk_ssusbsys.c
new file mode 100644
--- /dev/null
+++ b/sys/arm64/mediatek/mt7622_clk_ssusbsys.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2025 Martin Filla
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+#include <dev/fdt/simplebus.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dt-bindings/clock/mt7622-clk.h>
+#include <dt-bindings/reset/mt7622-reset.h>
+#include <dev/clk/clk_gate.h>
+#include "clkdev_if.h"
+#include "hwreset_if.h"
+#include "mdtk_clk.h"
+
+static struct ofw_compat_data compat_data[] = {
+ {"mediatek,mt7622-ssusbsys", 2},
+ {NULL, 0},
+};
+
+static struct clk_gate_def gates_ssusb_clk[] = {
+ GATE(CLK_SSUSB_U2_PHY_1P_EN, "ssusb_u2_phy_1p", "to_u2_phy_1p", 0x30, 0),
+ GATE(CLK_SSUSB_U2_PHY_EN, "ssusb_u2_phy_en", "to_u2_phy", 0x30, 1),
+ GATE(CLK_SSUSB_REF_EN, "ssusb_ref_en", "to_usb3_ref", 0x30, 5),
+ GATE(CLK_SSUSB_SYS_EN, "ssusb_sys_en", "to_usb3_sys", 0x30, 6),
+ GATE(CLK_SSUSB_MCU_EN, "ssusb_mcu_en", "axi_sel", 0x30, 7),
+ GATE(CLK_SSUSB_DMA_EN, "ssusb_dma_en", "hif_sel", 0x30, 8),
+};
+
+static struct mdtk_clk_def clk_ssusb_def = {
+ .gates_def = gates_ssusb_clk,
+ .num_gates = nitems(gates_ssusb_clk),
+};
+
+static int
+mt7622_ssusbsys_clk_detach(device_t dev) {
+ device_printf(dev, "Error: Clock driver cannot be detached\n");
+ return (EBUSY);
+}
+
+static int
+mt7622_ssusbsys_clk_probe(device_t dev) {
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) {
+ device_set_desc(dev, "Mediatek mt7622 ssusbsys clocks");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+mt7622_ssusbsys_clk_attach(device_t dev) {
+ struct mdtk_clk_softc *sc = device_get_softc(dev);
+ int rid;
+
+ sc->dev = dev;
+
+ mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (!sc->mem_res) {
+ device_printf(dev, "cannot allocate memory resource\n");
+ return (ENXIO);
+ }
+
+ mdtk_register_clocks(dev, &clk_ssusb_def);
+
+ return (0);
+}
+
+static int
+mt7622_ssusbsys_clk_hwreset_assert(device_t dev, intptr_t id, bool value) {
+ struct mdtk_clk_softc *sc = device_get_softc(dev);
+
+ return (mdtk_hwreset_by_idx(sc, id, value));
+}
+
+static device_method_t mt7622_ssusbsys_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, mt7622_ssusbsys_clk_probe),
+ DEVMETHOD(device_attach, mt7622_ssusbsys_clk_attach),
+ DEVMETHOD(device_detach, mt7622_ssusbsys_clk_detach),
+
+ /* Clkdev interface*/
+ DEVMETHOD(clkdev_read_4, mdtk_clkdev_read_4),
+ DEVMETHOD(clkdev_write_4, mdtk_clkdev_write_4),
+ DEVMETHOD(clkdev_modify_4, mdtk_clkdev_modify_4),
+ DEVMETHOD(clkdev_device_lock, mdtk_clkdev_device_lock),
+ DEVMETHOD(clkdev_device_unlock, mdtk_clkdev_device_unlock),
+
+ DEVMETHOD(hwreset_assert, mt7622_ssusbsys_clk_hwreset_assert),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(mt7622_ssusbsys, mt7622_ssusbsys_driver, mt7622_ssusbsys_methods,
+sizeof(struct mdtk_clk_softc));
+
+EARLY_DRIVER_MODULE(mt7622_ssusbsys, simplebus, mt7622_ssusbsys_driver, NULL, NULL,
+ BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE + 5);
diff --git a/sys/arm64/mediatek/mt7622_clk_topckgen.c b/sys/arm64/mediatek/mt7622_clk_topckgen.c
new file mode 100644
--- /dev/null
+++ b/sys/arm64/mediatek/mt7622_clk_topckgen.c
@@ -0,0 +1,579 @@
+/*
+ * Copyright (c) 2025 Martin Filla
+ * Copyright (c) 2025 Michal Meloun <mmel@FreeBSD.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+#include <dev/fdt/simplebus.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dt-bindings/clock/mt7622-clk.h>
+#include <dev/clk/clk_fixed.h>
+#include <dev/clk/clk_div.h>
+#include <dev/clk/clk_mux.h>
+#include <dev/clk/clk_gate.h>
+#include <dev/clk/clk_link.h>
+#include <arm64/mediatek/mdtk_clk.h>
+#include <dev/hwreset/hwreset.h>
+#include "clkdev_if.h"
+
+#define CLK_CFG_0 0x040
+#define CLK_CFG_1 0x050
+#define CLK_CFG_2 0x060
+#define CLK_CFG_3 0x070
+#define CLK_CFG_4 0x080
+#define CLK_CFG_5 0x090
+#define CLK_CFG_6 0x0A0
+#define CLK_CFG_7 0x0B0
+#define CLK_AUDDIV_0 0x120
+
+static struct ofw_compat_data compat_data[] = {
+ {"mediatek,mt7622-topckgen", 1},
+ {NULL, 0},
+};
+
+/* Parent lists */
+PLIST(eth_ck_parents) = {
+ "clkxtal",
+ "syspll1_d2",
+ "univpll1_d2",
+ "syspll1_d4",
+ "univpll_d5",
+ "sgmiipll_d2",
+ "univpll_d7",
+ "dmpll_ck"};
+
+PLIST(ddrphycfg_ck_parents) = {
+ "clkxtal",
+ "syspll1_d8"
+};
+
+PLIST(mem_ck_parents) = {
+ "clkxtal",
+ "dmpll_ck"
+};
+
+PLIST(axi_ck_parents) = {
+ "clkxtal",
+ "syspll1_d2",
+ "syspll_d5",
+ "syspll1_d4",
+ "univpll_d5",
+ "univpll2_d2",
+ "univpll_d7",
+ "dmpll_ck"
+};
+
+PLIST(pwm_ck_parents) = {
+ "clkxtal",
+ "univpll2_d4",
+ "univpll3_d2",
+ "univpll1_d4"
+};
+
+PLIST(f10m_ref_ck_parents) = {
+ "clkxtal",
+ "syspll4_d16"
+};
+
+PLIST(nfi_infra_ck_parents) = {
+ "clkxtal",
+ "clkxtal",
+ "clkxtal",
+ "clkxtal",
+ "clkxtal",
+ "clkxtal",
+ "clkxtal",
+ "clkxtal",
+ "univpll2_d8",
+ "syspll1_d8",
+ "univpll1_d8",
+ "syspll4_d2",
+ "univpll2_d4",
+ "univpll3_d2",
+ "syspll1_d4",
+ "syspll_d7"
+};
+
+PLIST(flash_ck_parents) = {
+ "clkxtal",
+ "univpll_div80_d4",
+ "syspll2_d8",
+ "syspll3_d4",
+ "univpll3_d4",
+ "univpll1_d8",
+ "syspll2_d4",
+ "univpll2_d4"
+};
+
+PLIST(uart_ck_parents) = {
+ "clkxtal",
+ "univpll2_d8"
+};
+
+PLIST(spi0_ck_parents) = {
+ "clkxtal",
+ "syspll3_d2",
+ "clkxtal",
+ "syspll2_d4",
+ "syspll4_d2",
+ "univpll2_d4",
+ "univpll1_d8",
+ "clkxtal"
+};
+
+PLIST(spi1_ck_parents) = {
+ "clkxtal",
+ "syspll3_d2",
+ "clkxtal",
+ "syspll2_d4",
+ "syspll4_d2",
+ "univpll2_d4",
+ "univpll1_d8",
+ "clkxtal"
+};
+
+PLIST(msdc50_0_ck_parents) = {
+ "clkxtal",
+ "univpll2_d8",
+ "univpll2_d4",
+ "syspll_d7",
+ "univpll2_d2",
+ "univpll_d5",
+ "univpll1_d2",
+ "univpll_d3"
+};
+
+PLIST(msdc30_0_ck_parents) = {
+ "clkxtal",
+ "univpll2_d16",
+ "univ48m_ck",
+ "syspll2_d4",
+ "univpll2_d4",
+ "syspll_d7",
+ "syspll2_d2",
+ "univpll2_d2"
+};
+
+PLIST(msdc30_1_ck_parents) = {
+ "clkxtal",
+ "univpll2_d16",
+ "univ48m_ck",
+ "syspll2_d4",
+ "univpll2_d4",
+ "syspll_d7",
+ "syspll2_d2",
+ "univpll2_d2"
+};
+
+PLIST(a1sys_hp_ck_parents) = {
+ "clkxtal",
+ "aud1pll_ck",
+ "aud2pll_ck",
+ "clkxtal"
+};
+
+PLIST(a2sys_hp_ck_parents) = {
+ "clkxtal",
+ "aud1pll_ck",
+ "aud2pll_ck",
+ "clkxtal"
+};
+
+PLIST(intdir_ck_parents) = {
+ "clkxtal",
+ "syspll_d2",
+ "univpll_d2",
+ "sgmiipll_ck"
+};
+
+PLIST(aud_intbus_ck_parents) = {
+ "clkxtal",
+ "syspll1_d4",
+ "syspll4_d2",
+ "syspll3_d2"
+};
+
+PLIST(pmicspi_ck_parents) = {
+ "clkxtal",
+ "syspll1_d8",
+ "syspll3_d4",
+ "syspll1_d16",
+ "univpll3_d4",
+ "univpll2_d16",
+ "dmpll_d8"
+};
+
+PLIST(scp_ck_parents) = {
+ "clkxtal",
+ "syspll1_d8",
+ "univpll2_d2",
+ "univpll2_d4"
+};
+
+PLIST(atb_ck_parents) = {
+ "clkxtal",
+ "syspll1_d2",
+ "syspll_d5",
+ "dmpll_ck"
+};
+
+PLIST(hif_ck_parents) = {
+ "clkxtal",
+ "syspll1_d2",
+ "univpll1_d2",
+ "syspll1_d4",
+ "univpll_d5",
+ "sgmiipll_d2",
+ "univpll_d7",
+ "dmpll_ck"
+};
+
+PLIST(audio_ck_parents) = {
+ "clkxtal",
+ "syspll3_d4",
+ "syspll4_d4",
+ "univpll1_d16"
+};
+
+PLIST(usb20_ck_parents) = {
+ "clkxtal",
+ "univpll3_d4",
+ "syspll1_d8",
+ "clkxtal"
+};
+
+PLIST(aud1_ck_parents) = {
+ "clkxtal",
+ "aud1pll_ck"
+};
+
+PLIST(aud2_ck_parents) = {
+ "clkxtal",
+ "aud2pll_ck"
+};
+
+PLIST(irrx_ck_parents) = {
+ "clkxtal",
+ "syspll4_d16"
+};
+
+PLIST(irtx_ck_parents) = {
+ "clkxtal",
+ "syspll4_d16"
+};
+
+PLIST(asm_l_ck_parents) = {
+ "clkxtal",
+ "syspll_d5",
+ "univpll2_d2",
+ "univpll2_d4"
+};
+
+PLIST(asm_m_ck_parents) = {
+ "clkxtal",
+ "syspll_d5",
+ "univpll2_d2",
+ "univpll2_d4"
+};
+
+PLIST(asm_h_ck_parents) = {
+ "clkxtal",
+ "syspll_d5",
+ "univpll2_d2",
+ "univpll2_d4"
+};
+
+PLIST(apll_ck_parents) = {
+ "aud1_sel",
+ "aud2_sel"
+};
+
+PLIST(apll2_ck_parents) = {
+ "aud2_sel",
+ "aud1_sel"
+};
+
+static struct clk_fixed_def fixed_clk[] = {
+ FRATE(CLK_TOP_TO_U2_PHY, "to_u2_phy", 31250000),
+ FRATE(CLK_TOP_TO_U2_PHY_1P, "to_u2_phy_1p", 31250000),
+ FRATE(CLK_TOP_PCIE0_PIPE_EN, "pcie0_pipe_en", 125000000),
+ FRATE(CLK_TOP_PCIE1_PIPE_EN, "pcie1_pipe_en", 125000000),
+ FRATE(CLK_TOP_SSUSB_TX250M, "ssusb_tx250m", 250000000),
+ FRATE(CLK_TOP_SSUSB_EQ_RX250M, "ssusb_eq_rx250m", 250000000),
+ FRATE(CLK_TOP_SSUSB_CDR_REF, "ssusb_cdr_ref", 33333333),
+ FRATE(CLK_TOP_SSUSB_CDR_FB, "ssusb_cdr_fb", 50000000),
+ FRATE(CLK_TOP_SATA_ASIC, "sata_asic", 50000000),
+ FRATE(CLK_TOP_SATA_RBC, "sata_rbc", 50000000),
+ FRATE(CLK_APMIXED_ARMPLL, "armpll", 120000000ULL),
+ FRATE(CLK_APMIXED_MAINPLL, "mainpll", 1120000000ULL),
+ FRATE(CLK_APMIXED_UNIV2PLL, "univ2pll", 2400000000ULL),
+ FRATE(CLK_APMIXED_ETH1PLL, "eth1pll", 500000000ULL),
+ FRATE(CLK_APMIXED_ETH2PLL, "eth2pll", 650000000ULL),
+ FRATE(CLK_APMIXED_AUD1PLL, "aud1pll", 147456000ULL),
+ FRATE(CLK_APMIXED_AUD2PLL, "aud2pll", 135475000ULL),
+ FRATE(CLK_APMIXED_TRGPLL, "trgpll", 725000000ULL),
+ FRATE(CLK_APMIXED_SGMIPLL, "sgmipll", 650000000ULL),
+
+ FFACT(CLK_TOP_TO_USB3_SYS, "to_usb3_sys", "eth1pll", 1, 4),
+ FFACT(CLK_TOP_P1_1MHZ, "p1_1mhz", "eth1pll", 1, 500),
+ FFACT(CLK_TOP_4MHZ, "free_run_4mhz", "eth1pll", 1, 125),
+ FFACT(CLK_TOP_P0_1MHZ, "p0_1mhz", "eth1pll", 1, 500),
+ FFACT(CLK_TOP_TXCLK_SRC_PRE, "txclk_src_pre", "sgmiipll_d2", 1, 1),
+ FFACT(CLK_TOP_RTC, "rtc", "clkxtal", 1, 1024),
+ FFACT(CLK_TOP_MEMPLL, "mempll", "clkxtal", 32, 1),
+ FFACT(CLK_TOP_DMPLL, "dmpll_ck", "mempll", 1, 1),
+ FFACT(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll", 1, 2),
+ FFACT(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "mainpll", 1, 4),
+ FFACT(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "mainpll", 1, 8),
+ FFACT(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "mainpll", 1, 16),
+ FFACT(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "mainpll", 1, 12),
+ FFACT(CLK_TOP_SYSPLL2_D8, "syspll2_d8", "mainpll", 1, 24),
+ FFACT(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, 5),
+ FFACT(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "mainpll", 1, 10),
+ FFACT(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "mainpll", 1, 20),
+ FFACT(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "mainpll", 1, 14),
+ FFACT(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "mainpll", 1, 28),
+ FFACT(CLK_TOP_SYSPLL4_D16, "syspll4_d16", "mainpll", 1, 112),
+ FFACT(CLK_TOP_UNIVPLL, "univpll", "univ2pll", 1, 2),
+ FFACT(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2),
+ FFACT(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll", 1, 4),
+ FFACT(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll", 1, 8),
+ FFACT(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll", 1, 16),
+ FFACT(CLK_TOP_UNIVPLL1_D16, "univpll1_d16", "univpll", 1, 32),
+ FFACT(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll", 1, 6),
+ FFACT(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll", 1, 12),
+ FFACT(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll", 1, 24),
+ FFACT(CLK_TOP_UNIVPLL2_D16, "univpll2_d16", "univpll", 1, 48),
+ FFACT(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5),
+ FFACT(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll", 1, 10),
+ FFACT(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll", 1, 20),
+ FFACT(CLK_TOP_UNIVPLL3_D16, "univpll3_d16", "univpll", 1, 80),
+ FFACT(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7),
+ FFACT(CLK_TOP_UNIVPLL_D80_D4, "univpll_div80_d4", "univpll", 1, 320),
+ FFACT(CLK_TOP_SGMIIPLL, "sgmiipll_ck", "sgmipll", 1, 1),
+ FFACT(CLK_TOP_SGMIIPLL_D2, "sgmiipll_d2", "sgmipll", 1, 2),
+
+ FFACT(/*CLK_TOP_SYSPLL_D7*/ 0, "syspll_d7", "mainpll", 1, 8),
+ FFACT(/*CLK_TOP_SYSPLL2_D2 */0, "syspll2_d2", "mainpll", 1, 6),
+ FFACT(/*CLK_TOP_UNIVPLL_D3*/ 0, "univpll_d3", "univpll", 1, 3),
+ FFACT(/*CLK_TOP_SYSPLL1_D16*/ 0, "syspll1_d16", "syspll_d2", 1, 16),
+ FFACT(/*CLK_TOP_DMPLL_D8*/ 0, "dmpll_d8", "dmpll_ck", 1, 8),
+ FFACT(CLK_TOP_AUD1PLL, "aud1pll_ck", "aud1pll", 1, 1),
+ FFACT(CLK_TOP_AUD2PLL, "aud2pll_ck", "aud2pll", 1, 1),
+ FFACT(CLK_TOP_UNIV48M, "univ48m_ck", "univpll", 1, 25),
+ FFACT(CLK_TOP_TO_USB3_REF, "to_usb3_ref", "univpll2_d4", 1, 4),
+ FFACT(CLK_TOP_PCIE1_MAC_EN, "pcie1_mac_en", "univpll1_d4", 1, 1),
+ FFACT(CLK_TOP_PCIE0_MAC_EN, "pcie0_mac_en", "univpll1_d4", 1, 1),
+ FFACT(CLK_TOP_ETH_500M, "eth_500m", "eth1pll", 1, 1),
+ FFACT(CLK_TOP_AUD_I2S2_MCK, "aud_i2s2_mck", "i2s2_mck_sel", 1, 2),
+};
+
+static struct clk_gate_def gates_clk[] = {
+ I_GATE(CLK_TOP_ETH_SEL, "eth_sel", "eth_sel_mux", CLK_CFG_0, 31),
+ I_GATE(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", "ddrphycfg_sel_mux", CLK_CFG_0, 23),
+ I_GATE(CLK_TOP_MEM_SEL, "mem_sel", "mem_sel_mux", CLK_CFG_0, 15),
+ I_GATE(CLK_TOP_AXI_SEL, "axi_sel", "axi_sel_mux", CLK_CFG_0, 7),
+
+ I_GATE(CLK_TOP_PWM_SEL, "pwm_sel", "pwm_sel_mux", CLK_CFG_1, 7),
+ I_GATE(CLK_TOP_F10M_REF_SEL, "f10m_ref_sel", "f10m_ref_sel_mux", CLK_CFG_1, 15),
+ I_GATE(CLK_TOP_NFI_INFRA_SEL, "spinfi_infra_bclk_sel", "spinfi_infra_bclk_sel_mux", CLK_CFG_1, 23),
+ I_GATE(CLK_TOP_FLASH_SEL, "flash_sel", "flash_sel_mux", CLK_CFG_1, 31),
+
+ I_GATE(CLK_TOP_UART_SEL, "uart_sel", "uart_sel_mux", CLK_CFG_2, 7),
+ I_GATE(CLK_TOP_SPI0_SEL, "spi0_sel", "spi0_sel_mux", CLK_CFG_2, 15),
+ I_GATE(CLK_TOP_SPI1_SEL, "spi1_sel", "spi1_sel_mux", CLK_CFG_2, 23),
+ I_GATE(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", "msdc50_0_sel_mux", CLK_CFG_2, 31),
+
+ I_GATE(CLK_TOP_MSDC30_0_SEL, "msdc30_0_sel", "msdc30_0_sel_mux", CLK_CFG_3, 7),
+ I_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", "msdc30_1_sel_mux", CLK_CFG_3, 15),
+ I_GATE(CLK_TOP_A1SYS_HP_SEL, "a1sys_hp_sel", "a1sys_hp_sel_mux", CLK_CFG_3, 23),
+ I_GATE(CLK_TOP_A2SYS_HP_SEL, "a2sys_hp_sel", "a2sys_hp_sel_mux", CLK_CFG_3, 31),
+
+ I_GATE(CLK_TOP_INTDIR_SEL, "intdir_sel", "intdir_sel_mux", CLK_CFG_4, 7),
+ I_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", "aud_intbus_sel_mux", CLK_CFG_4, 15),
+ I_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", "pmicspi_sel_mux", CLK_CFG_4, 23),
+ I_GATE(CLK_TOP_SCP_SEL, "scp_sel", "scp_sel_mux", CLK_CFG_4, 31),
+
+ I_GATE(CLK_TOP_ATB_SEL, "atb_sel", "atb_sel_mux", CLK_CFG_5, 7),
+ I_GATE(CLK_TOP_HIF_SEL, "hif_sel", "hif_sel_mux", CLK_CFG_5, 15),
+ I_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", "audio_sel_mux", CLK_CFG_5, 23),
+ I_GATE(CLK_TOP_AUDIO_SEL, "usb20_sel", "usb20_sel_mux", CLK_CFG_5, 31),
+
+ I_GATE(CLK_TOP_AUD1_SEL, "aud1_sel", "aud1_sel_mux", CLK_CFG_6, 7),
+ I_GATE(CLK_TOP_AUD2_SEL, "aud2_sel", "aud2_sel_mux", CLK_CFG_6, 15),
+ I_GATE(CLK_TOP_IRRX_SEL, "irrx_sel_sel", "irrx_sel_mux", CLK_CFG_6, 23),
+ I_GATE(CLK_TOP_IRTX_SEL, "irtx_sel", "irtx_sel_mux", CLK_CFG_6, 31),
+
+ I_GATE(CLK_TOP_ASM_L_SEL, "asm_l_sel", "asm_l_sel_mux", CLK_CFG_6, 7),
+ I_GATE(CLK_TOP_ASM_M_SEL, "asm_m_sel", "asm_m_sel_mux", CLK_CFG_6, 15),
+ I_GATE(CLK_TOP_ASM_H_SEL, "asm_h_sel", "asm_h_sel_mux", CLK_CFG_6, 23),
+
+ I_GATE(CLK_TOP_APLL1_SEL, "apll1_ck_sel", "apll1_ck_div", CLK_AUDDIV_0, 0),
+ I_GATE(CLK_TOP_APLL2_SEL, "apll2_ck_sel", "apll2_ck_div", CLK_AUDDIV_0, 0),
+ I_GATE(CLK_TOP_I2S0_MCK_SEL, "i2s0_mck_sel", "i2s0_mck_div", CLK_AUDDIV_0, 0),
+ I_GATE(CLK_TOP_I2S1_MCK_SEL, "i2s1_mck_sel", "i2s1_mck_div", CLK_AUDDIV_0, 0),
+ I_GATE(CLK_TOP_I2S2_MCK_SEL, "i2s2_mck_sel", "i2s2_mck_div", CLK_AUDDIV_0, 0),
+ I_GATE(CLK_TOP_I2S3_MCK_SEL, "i2s3_mck_sel", "i2s3_mck_div", CLK_AUDDIV_0, 0),
+};
+
+static struct clk_mux_def muxes_clk[] = {
+ MUX0(0, "eth_sel_mux", eth_ck_parents, CLK_CFG_0, 24, 3),
+ MUX0(0, "ddrphycfg_sel_mux", ddrphycfg_ck_parents, CLK_CFG_0, 16, 1),
+ MUX0(0, "mem_sel_mux", mem_ck_parents, CLK_CFG_0, 8, 1),
+ MUX0(0, "axi_sel_mux", axi_ck_parents, CLK_CFG_0, 0, 3),
+
+ MUX0(0, "pwm_sel_mux", pwm_ck_parents, CLK_CFG_1, 0, 2),
+ MUX0(0, "f10m_ref_sel_mux", f10m_ref_ck_parents, CLK_CFG_1, 8, 1),
+ MUX0(0, "spinfi_infra_bclk_sel_mux", nfi_infra_ck_parents, CLK_CFG_1, 16, 4),
+ MUX0(0, "flash_sel_mux", flash_ck_parents, CLK_CFG_1, 24, 3),
+
+ MUX0(0, "uart_sel_mux", uart_ck_parents, CLK_CFG_2, 0, 1),
+ MUX0(0, "spi0_sel_mux", spi0_ck_parents, CLK_CFG_2, 8, 3),
+ MUX0(0, "spi1_sel_mux", spi1_ck_parents, CLK_CFG_2, 16, 3),
+ MUX0(0, "msdc50_0_sel_mux", msdc50_0_ck_parents, CLK_CFG_2, 24, 3),
+
+ MUX0(0, "msdc30_0_sel_mux", msdc30_0_ck_parents, CLK_CFG_3, 0, 3),
+ MUX0(0, "msdc30_1_sel_mux", msdc30_1_ck_parents, CLK_CFG_3, 8, 3),
+ MUX0(0, "a1sys_hp_sel_mux", a1sys_hp_ck_parents, CLK_CFG_3, 16, 2),
+ MUX0(0, "a2sys_hp_sel_mux", a2sys_hp_ck_parents, CLK_CFG_3, 24, 2),
+
+ MUX0(0, "intdir_sel_mux", intdir_ck_parents, CLK_CFG_4, 0, 2),
+ MUX0(0, "aud_intbus_sel_mux", aud_intbus_ck_parents, CLK_CFG_4, 8, 2),
+ MUX0(0, "pmicspi_sel_mux", pmicspi_ck_parents, CLK_CFG_4, 16, 3),
+ MUX0(0, "scp_sel_mux", scp_ck_parents, CLK_CFG_4, 24, 2),
+
+ MUX0(0, "atb_sel_mux", atb_ck_parents, CLK_CFG_5, 0, 2),
+ MUX0(0, "hif_sel_mux", hif_ck_parents, CLK_CFG_5, 8, 3),
+ MUX0(0, "audio_sel_mux", audio_ck_parents, CLK_CFG_5, 8, 3),
+ MUX0(0, "usb20_sel_mux", usb20_ck_parents, CLK_CFG_5, 24, 2),
+
+ MUX0(0, "aud1_sel_mux", aud1_ck_parents, CLK_CFG_6, 0, 1),
+ MUX0(0, "aud2_sel_mux", aud2_ck_parents, CLK_CFG_6, 8, 1),
+ MUX0(0, "irrx_sel_mux", irrx_ck_parents, CLK_CFG_6, 16, 1),
+ MUX0(0, "irtx_sel_mux", irtx_ck_parents, CLK_CFG_6, 24, 1),
+
+ MUX0(0, "asm_l_sel_mux", asm_l_ck_parents, CLK_CFG_7, 0, 2),
+ MUX0(0, "asm_m_sel_mux", asm_m_ck_parents, CLK_CFG_7, 8, 2),
+ MUX0(0, "asm_h_sel_mux", asm_h_ck_parents, CLK_CFG_7, 16, 2),
+
+ MUX0(0, "apll1_ck_mux", apll_ck_parents, CLK_AUDDIV_0, 6, 1),
+ MUX0(0, "apll2_ck_mux", apll2_ck_parents, CLK_AUDDIV_0, 7, 1),
+ MUX0(0, "i2s0_mck_mux", apll_ck_parents, CLK_AUDDIV_0, 8, 1),
+ MUX0(0, "i2s1_mck_mux", apll_ck_parents, CLK_AUDDIV_0, 9, 1),
+ MUX0(0, "i2s2_mck_mux", apll_ck_parents, CLK_AUDDIV_0, 10, 1),
+ MUX0(0, "i2s3_mck_mux", apll_ck_parents, CLK_AUDDIV_0, 11, 1),
+};
+
+static struct clk_div_def dived_clk[] = {
+ DIV(CLK_TOP_APLL1_DIV, "apll1_ck_div", "apll1_ck_mux",
+ 0x120, 24, 3),
+ DIV(CLK_TOP_APLL2_DIV, "apll2_ck_div", "apll2_ck_mux",
+ 0x120, 28, 3),
+ DIV(CLK_TOP_I2S0_MCK_DIV, "i2s0_mck_div", "i2s0_mck_mux",
+ 0x124, 0, 7),
+ DIV(CLK_TOP_I2S1_MCK_DIV, "i2s1_mck_div", "i2s1_mck_mux",
+ 0x124, 8, 7),
+ DIV(CLK_TOP_I2S2_MCK_DIV, "i2s2_mck_div", "i2s2_mck_mux",
+ 0x124, 16, 7),
+ DIV(CLK_TOP_I2S3_MCK_DIV, "i2s3_mck_div", "i2s3_mck_mux",
+ 0x124, 24, 7),
+ DIV(CLK_TOP_A1SYS_HP_DIV, "a1sys_div", "a1sys_hp_sel",
+ 0x128, 8, 7),
+ DIV(CLK_TOP_A2SYS_HP_DIV, "a2sys_div", "a2sys_hp_sel",
+ 0x128, 24, 7),
+};
+
+static struct mdtk_clk_def clk_def = {
+ .linked_def = NULL,
+ .num_linked = 0,
+ .fixed_def = fixed_clk,
+ .num_fixed = nitems(fixed_clk),
+ .gates_def = gates_clk,
+ .num_gates = nitems(gates_clk),
+ .dived_def = dived_clk,
+ .num_dived = nitems(dived_clk),
+ .muxes_def = muxes_clk,
+ .num_muxes = nitems(muxes_clk),
+};
+
+static int
+topckgen_clk_detach(device_t dev) {
+ device_printf(dev, "Error: Clock driver cannot be detached\n");
+ return (EBUSY);
+}
+
+static int
+topckgen_clk_probe(device_t dev) {
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) {
+ device_set_desc(dev, "Mediatek Topckgen clocks");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+topckgen_clk_attach(device_t dev) {
+ struct mdtk_clk_softc *sc = device_get_softc(dev);
+ int rid, rv;
+
+ sc->dev = dev;
+
+ mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+
+ /* Resource setup. */
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (!sc->mem_res) {
+ device_printf(dev, "cannot allocate memory resource\n");
+ rv = ENXIO;
+ goto fail;
+ }
+
+ mdtk_register_clocks(dev, &clk_def);
+ return (0);
+
+ fail:
+ if (sc->mem_res)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
+
+ return (rv);
+}
+
+static device_method_t mdtk_mt7622_topckgen_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, topckgen_clk_probe),
+ DEVMETHOD(device_attach, topckgen_clk_attach),
+ DEVMETHOD(device_detach, topckgen_clk_detach),
+
+ /* Clkdev interface*/
+ DEVMETHOD(clkdev_read_4, mdtk_clkdev_read_4),
+ DEVMETHOD(clkdev_write_4, mdtk_clkdev_write_4),
+ DEVMETHOD(clkdev_modify_4, mdtk_clkdev_modify_4),
+ DEVMETHOD(clkdev_device_lock, mdtk_clkdev_device_lock),
+ DEVMETHOD(clkdev_device_unlock, mdtk_clkdev_device_unlock),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(mdtk_mt7622_topckgen, mdtk_mt7622_topckgen_driver, mdtk_mt7622_topckgen_methods,
+sizeof(struct mdtk_clk_softc));
+
+EARLY_DRIVER_MODULE(mdtk_mt7622_topckgen, simplebus, mdtk_mt7622_topckgen_driver, NULL, NULL,
+ BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE + 2);
\ No newline at end of file
diff --git a/sys/arm64/mediatek/mt_uart.c b/sys/arm64/mediatek/mt_uart.c
new file mode 100644
--- /dev/null
+++ b/sys/arm64/mediatek/mt_uart.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2025 Martin Filla
+ * Copyright (c) 2025 Michal Meloun <mmel@FreeBSD.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/cdefs.h>
+/*
+ * UART driver for mediatek SoCs.
+ */
+#include "opt_platform.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/sysctl.h>
+#include <machine/bus.h>
+
+#include <dev/clk/clk.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_cpu.h>
+#include <dev/uart/uart_cpu_fdt.h>
+#include <dev/uart/uart_bus.h>
+#include <dev/uart/uart_dev_ns8250.h>
+#include <dev/ic/ns16550.h>
+
+#include "uart_if.h"
+
+/*
+ * High-level UART interface.
+ */
+struct mt_softc {
+ struct ns8250_softc ns8250_base;
+ clk_t baud_clk;
+ clk_t bus_clk;
+};
+
+/*
+ * UART class interface.
+ */
+static int
+mt_uart_attach(struct uart_softc *sc)
+{
+ int rv;
+ struct ns8250_softc *ns8250 = (struct ns8250_softc *)sc;
+ struct uart_bas *bas = &sc->sc_bas;
+
+ rv = ns8250_bus_attach(sc);
+ if (rv != 0)
+ return (rv);
+
+ ns8250->ier_mask = 0xc0;
+ ns8250->ier = uart_getreg(bas, REG_IER) & ns8250->ier_mask;
+ ns8250->ier |= ns8250->ier_rxbits;
+ uart_setreg(bas, REG_IER, ns8250->ier);
+ uart_barrier(bas);
+ return (0);
+}
+
+static kobj_method_t mt_methods[] = {
+ KOBJMETHOD(uart_probe, ns8250_bus_probe),
+ KOBJMETHOD(uart_attach, mt_uart_attach),
+ KOBJMETHOD(uart_detach, ns8250_bus_detach),
+ KOBJMETHOD(uart_flush, ns8250_bus_flush),
+ KOBJMETHOD(uart_getsig, ns8250_bus_getsig),
+ KOBJMETHOD(uart_ioctl, ns8250_bus_ioctl),
+ KOBJMETHOD(uart_ipend, ns8250_bus_ipend),
+ KOBJMETHOD(uart_param, ns8250_bus_param),
+ KOBJMETHOD(uart_receive, ns8250_bus_receive),
+ KOBJMETHOD(uart_setsig, ns8250_bus_setsig),
+ KOBJMETHOD(uart_transmit, ns8250_bus_transmit),
+ KOBJMETHOD(uart_txbusy, ns8250_bus_txbusy),
+ KOBJMETHOD(uart_grab, ns8250_bus_grab),
+ KOBJMETHOD(uart_ungrab, ns8250_bus_ungrab),
+ KOBJMETHOD_END
+};
+
+static struct uart_class mt_uart_class = {
+ "mediatek class",
+ mt_methods,
+ sizeof(struct mt_softc),
+ .uc_ops = &uart_ns8250_ops,
+ .uc_range = 8,
+ .uc_rclk = 0,
+ .uc_rshift = 2,
+ .uc_riowidth = 4,
+};
+
+/* Compatible devices. */
+static struct ofw_compat_data compat_data[] = {
+ {"mediatek,mt6577-uart", (uintptr_t)&mt_uart_class},
+ {NULL, (uintptr_t)NULL},
+};
+
+UART_FDT_CLASS(compat_data);
+
+/*
+ * UART Driver interface.
+ */
+static int
+uart_fdt_get_shift1(phandle_t node)
+{
+ pcell_t shift;
+
+ if ((OF_getencprop(node, "reg-shift", &shift, sizeof(shift))) <= 0)
+ shift = 2;
+ return ((int)shift);
+}
+
+static int
+mt_uart_probe(device_t dev)
+{
+ struct mt_softc *sc;
+ phandle_t node;
+ uint64_t freq;
+ int shift;
+ int rv;
+ const struct ofw_compat_data *cd;
+
+ sc = device_get_softc(dev);
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+ cd = ofw_bus_search_compatible(dev, compat_data);
+ if (cd->ocd_data == 0)
+ return (ENXIO);
+ sc->ns8250_base.base.sc_class = (struct uart_class *)cd->ocd_data;
+
+ node = ofw_bus_get_node(dev);
+ shift = uart_fdt_get_shift1(node);
+ rv = clk_get_by_ofw_name(dev, 0, "baud", &sc->baud_clk);
+ if (rv != 0) {
+ device_printf(dev, "Cannot get UART baud clock: %d\n", rv);
+ return (ENXIO);
+ }
+ rv = clk_enable(sc->baud_clk);
+ if (rv != 0) {
+ device_printf(dev, "Cannot enable UART baud clock: %d\n", rv);
+ return (ENXIO);
+ }
+
+ rv = clk_get_by_ofw_name(dev, 0, "bus", &sc->bus_clk);
+ if (rv != 0) {
+ device_printf(dev, "Cannot get UART bus clock: %d\n", rv);
+ return (ENXIO);
+ }
+ rv = clk_enable(sc->bus_clk);
+ if (rv != 0) {
+ device_printf(dev, "Cannot enable UART bus clock: %d\n", rv);
+ return (ENXIO);
+ }
+
+ rv = clk_get_freq(sc->baud_clk, &freq);
+ if (rv != 0) {
+ device_printf(dev, "Cannot get freq UART clock: %d\n", rv);
+ return (ENXIO);
+ }
+
+ return (uart_bus_probe(dev, shift, 0, (int)freq, 0, 0, 0));
+}
+
+static int
+mt_uart_detach(device_t dev)
+{
+ struct mt_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (sc->baud_clk != NULL) {
+ clk_release(sc->baud_clk);
+ }
+
+ if (sc->bus_clk != NULL) {
+ clk_release(sc->bus_clk);
+ }
+
+
+ return (uart_bus_detach(dev));
+}
+
+static device_method_t mt_uart_bus_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, mt_uart_probe),
+ DEVMETHOD(device_attach, uart_bus_attach),
+ DEVMETHOD(device_detach, mt_uart_detach),
+ DEVMETHOD_END
+};
+
+static driver_t mt_uart_driver = {
+ uart_driver_name,
+ mt_uart_bus_methods,
+ sizeof(struct mt_softc),
+};
+
+DRIVER_MODULE(mdtk_uart, simplebus, mt_uart_driver, 0, 0);
diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -853,3 +853,15 @@
dev/clk/xilinx/zynqmp_clk_mux.c optional fdt soc_xilinx_zynq
dev/clk/xilinx/zynqmp_clk_pll.c optional fdt soc_xilinx_zynq
dev/clk/xilinx/zynqmp_reset.c optional fdt soc_xilinx_zynq
+
+# Mediatek
+arm64/mediatek/mt_uart.c optional fdt soc_mediatek
+arm64/mediatek/mt7622_clk_topckgen.c optional clk fdt soc_mediatek
+arm64/mediatek/mt7622_clk_pericfg.c optional clk fdt soc_mediatek
+arm64/mediatek/mt7622_clk_infracfg.c optional clk fdt soc_mediatek
+arm64/mediatek/mt7622_clk_audio.c optional clk fdt soc_mediatek
+arm64/mediatek/mt7622_clk_eth.c optional clk fdt soc_mediatek
+arm64/mediatek/mt7622_clk_sgmii.c optional clk fdt soc_mediatek
+arm64/mediatek/mt7622_clk_ssusbsys.c optional clk fdt soc_mediatek
+arm64/mediatek/mt7622_clk_pciesys.c optional clk fdt soc_mediatek
+arm64/mediatek/mdtk_clk.c optional clk fdt soc_mediatek
diff --git a/sys/conf/options.arm64 b/sys/conf/options.arm64
--- a/sys/conf/options.arm64
+++ b/sys/conf/options.arm64
@@ -39,6 +39,7 @@
SOC_HISI_HI6220 opt_soc.h
SOC_INTEL_STRATIX10 opt_soc.h
SOC_MARVELL_8K opt_soc.h
+SOC_MEDIATEK opt_soc.h
SOC_NVIDIA_TEGRA210 opt_soc.h
SOC_NXP_LS opt_soc.h
SOC_ROCKCHIP opt_soc.h
diff --git a/sys/modules/dtb/mediatek/Makefile b/sys/modules/dtb/mediatek/Makefile
new file mode 100644
--- /dev/null
+++ b/sys/modules/dtb/mediatek/Makefile
@@ -0,0 +1,7 @@
+.if ${MACHINE_ARCH} == "aarch64"
+DTS= mediatek/mt7622-bananapi-bpi-r64.dts \
+ mediatek/mt7986a-bananapi-bpi-r3-mini.dts \
+ mediatek/mt7986a-bananapi-bpi-r3.dts
+.endif
+
+.include <bsd.dtb.mk>
\ No newline at end of file
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Jul 24, 8:51 AM (15 h, 3 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35439579
Default Alt Text
D57732.diff (76 KB)
Attached To
Mode
D57732: arm64: mediatek: add initial MT7622/Banana Pi R64 support
Attached
Detach File
Event Timeline
Log In to Comment