git: 550db3d6f502 - main - sdhci: Initial support for the SpacemiT K1 sdhci controller

From: Bojan Novković <bnovkov_at_FreeBSD.org>
Date: Sun, 16 Aug 2026 17:17:15 UTC
The branch main has been updated by bnovkov:

URL: https://cgit.FreeBSD.org/src/commit/?id=550db3d6f502946f6cf01eeb34f53e70395ddc6f

commit 550db3d6f502946f6cf01eeb34f53e70395ddc6f
Author:     Bojan Novković <bnovkov@FreeBSD.org>
AuthorDate: 2026-05-19 21:07:12 +0000
Commit:     Bojan Novković <bnovkov@FreeBSD.org>
CommitDate: 2026-08-16 17:15:52 +0000

    sdhci: Initial support for the SpacemiT K1 sdhci controller
    
    Reviewed by:    mhorne
    Differential Revision:  https://reviews.freebsd.org/D57178
---
 sys/dev/sdhci/sdhci_fdt_spacemit.c | 134 +++++++++++++++++++++++++++++++++++++
 sys/riscv/spacemit/files.spacemit  |   2 +
 2 files changed, 136 insertions(+)

diff --git a/sys/dev/sdhci/sdhci_fdt_spacemit.c b/sys/dev/sdhci/sdhci_fdt_spacemit.c
new file mode 100644
index 000000000000..d516ce60f889
--- /dev/null
+++ b/sys/dev/sdhci/sdhci_fdt_spacemit.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2026 Bojan Novković <bnovkov@FreeBSD.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/types.h>
+#include <sys/taskqueue.h>
+#include <sys/module.h>
+
+#include <machine/bus.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/ofw_subr.h>
+#include <dev/clk/clk.h>
+#include <dev/ofw/openfirm.h>
+
+#include <dev/hwreset/hwreset.h>
+#include <dev/phy/phy.h>
+#include <dev/mmc/bridge.h>
+#include <dev/mmc/mmcbrvar.h>
+#include <dev/mmc/mmcreg.h>
+
+#include <dev/sdhci/sdhci.h>
+#include <dev/sdhci/sdhci_fdt.h>
+
+#include "mmcbr_if.h"
+#include "sdhci_if.h"
+
+#include "opt_mmccam.h"
+#include "opt_soc.h"
+
+static struct ofw_compat_data compat_data[] = {
+	{ "spacemit,k1-sdhci", 1 },
+	{ NULL, 0 }
+};
+
+static int
+sdhci_fdt_spacemit_probe(device_t dev)
+{
+
+	if (!ofw_bus_status_okay(dev))
+		return (ENXIO);
+
+	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+		return (ENXIO);
+
+	if (ofw_bus_has_prop(dev, "no-sd")) {
+		/* XXX: only attach to the SD card for now. */
+		device_printf(dev, "MMC and SDIO aren't supported yet\n");
+		return (ENXIO);
+	}
+
+	device_set_desc(dev, "SpacemiT K1 SDHCI controller");
+
+	return (BUS_PROBE_DEFAULT);
+}
+
+static int
+sdhci_fdt_spacemit_attach(device_t dev)
+{
+	struct sdhci_fdt_softc *sc;
+	clk_t clk_core;
+	hwreset_t rst;
+
+	sc = device_get_softc(dev);
+	sc->quirks = SDHCI_QUIRK_PRESET_VALUE_BROKEN |
+		SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
+
+	if (clk_get_by_ofw_name(dev, 0, "core", &clk_core)) {
+		device_printf(dev, "cannot get core clock\n");
+		return (ENXIO);
+	}
+	if (clk_get_by_ofw_name(dev, 0, "io", &sc->clk_core)) {
+		device_printf(dev, "cannot get io clock\n");
+		return (ENXIO);
+	}
+	if (hwreset_get_by_ofw_name(dev, 0, "sdh", &rst) != 0) {
+		device_printf(dev, "cannot get device reset\n");
+		return (ENXIO);
+	}
+
+	if (hwreset_deassert(rst) != 0) {
+		device_printf(dev, "cannot reset device\n");
+		return (ENXIO);
+	}
+	if (clk_enable(clk_core) != 0) {
+		device_printf(dev, "cannot enable core clock\n");
+		return (ENXIO);
+	}
+	if (clk_enable(sc->clk_core) != 0) {
+		device_printf(dev, "cannot enable io clock\n");
+		return (ENXIO);
+	}
+
+	return (sdhci_fdt_attach(dev));
+}
+
+static int
+sdhci_fdt_spacemit_set_clock(device_t dev, struct sdhci_slot *slot, int clock)
+{
+	struct sdhci_fdt_softc *sc = device_get_softc(dev);
+	uint64_t freq;
+
+	sc = device_get_softc(dev);
+
+	clk_set_freq(sc->clk_core, clock, CLK_SET_ROUND_ANY);
+	clk_get_freq(sc->clk_core, &freq);
+
+	return ((int)freq);
+}
+
+static device_method_t sdhci_fdt_spacemit_methods[] = {
+	/* device_if */
+	DEVMETHOD(device_probe,		sdhci_fdt_spacemit_probe),
+	DEVMETHOD(device_attach,	sdhci_fdt_spacemit_attach),
+
+	DEVMETHOD(sdhci_set_clock,	sdhci_fdt_spacemit_set_clock),
+	DEVMETHOD_END
+};
+extern driver_t sdhci_fdt_driver;
+
+DEFINE_CLASS_1(sdhci_spacemit, sdhci_fdt_spacemit_driver, sdhci_fdt_spacemit_methods,
+    sizeof(struct sdhci_fdt_softc), sdhci_fdt_driver);
+DRIVER_MODULE(sdhci_spacemit, simplebus, sdhci_fdt_spacemit_driver, NULL, NULL);
+
+#ifndef MMCCAM
+MMC_DECLARE_BRIDGE(sdhci_fdt_spacemit);
+#endif
diff --git a/sys/riscv/spacemit/files.spacemit b/sys/riscv/spacemit/files.spacemit
index b4ab14e9240b..2b0d5cfdb343 100644
--- a/sys/riscv/spacemit/files.spacemit
+++ b/sys/riscv/spacemit/files.spacemit
@@ -1,3 +1,5 @@
 dev/clk/spacemit/k1_clk.c	optional k1_ccu fdt
 dev/clk/spacemit/k1_pll.c	optional k1_ccu fdt
 dev/clk/spacemit/k1_apmu.c	optional k1_ccu fdt
+
+dev/sdhci/sdhci_fdt_spacemit.c	optional fdt sdhci sdhci_spacemit