Module Name: src
Committed By: skrll
Date: Wed Sep 18 10:37:03 UTC 2024
Modified Files:
src/sys/arch/riscv/starfive: jh7110_clkc.c jh71x0_clkc.h
Log Message:
risc-v: add reset support to the JH7110 SOC clock controller driver
To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/riscv/starfive/jh7110_clkc.c
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/riscv/starfive/jh71x0_clkc.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/riscv/starfive/jh7110_clkc.c
diff -u src/sys/arch/riscv/starfive/jh7110_clkc.c:1.4 src/sys/arch/riscv/starfive/jh7110_clkc.c:1.5
--- src/sys/arch/riscv/starfive/jh7110_clkc.c:1.4 Wed Sep 18 10:33:35 2024
+++ src/sys/arch/riscv/starfive/jh7110_clkc.c Wed Sep 18 10:37:03 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: jh7110_clkc.c,v 1.4 2024/09/18 10:33:35 skrll Exp $ */
+/* $NetBSD: jh7110_clkc.c,v 1.5 2024/09/18 10:37:03 skrll Exp $ */
/*-
* Copyright (c) 2023 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: jh7110_clkc.c,v 1.4 2024/09/18 10:33:35 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: jh7110_clkc.c,v 1.5 2024/09/18 10:37:03 skrll Exp $");
#include <sys/param.h>
@@ -841,9 +841,66 @@ static struct jh7110_clock_config jh7110
};
+#define JH7110_SYSRST_ASSERT 0x2f8
+#define JH7110_SYSRST_STATUS 0x308
+#define JH7110_SYSRST_NRESETS 126
+
+#define JH7110_AONRST_ASSERT 0x38
+#define JH7110_AONRST_STATUS 0x3c
+#define JH7110_AONRST_NRESETS 8
+
+#define JH7110_STGRST_ASSERT 0x74
+#define JH7110_STGRST_STATUS 0x78
+#define JH7110_STGRST_NRESETS 23
+
+#define JH7110_ISPRST_ASSERT 0x38
+#define JH7110_ISPRST_STATUS 0x3c
+#define JH7110_ISPRST_NRESETS 12
+
+#define JH7110_VOUTRST_ASSERT 0x48
+#define JH7110_VOUTRST_STATUS 0x4c
+#define JH7110_VOUTRST_NRESETS 12
+
+struct jh7110_reset_config {
+ size_t jhcr_nresets;
+ bus_size_t jhcr_assert;
+ bus_size_t jhcr_status;
+};
+
+static struct jh7110_reset_config jh7110_sysrst_config = {
+ .jhcr_nresets = JH7110_SYSRST_NRESETS,
+ .jhcr_assert = JH7110_SYSRST_ASSERT,
+ .jhcr_status = JH7110_SYSRST_STATUS,
+};
+
+static struct jh7110_reset_config jh7110_aonrst_config = {
+ .jhcr_nresets = JH7110_AONRST_NRESETS,
+ .jhcr_assert = JH7110_AONRST_ASSERT,
+ .jhcr_status = JH7110_AONRST_STATUS,
+};
+
+static struct jh7110_reset_config jh7110_stgrst_config = {
+ .jhcr_nresets = JH7110_STGRST_NRESETS,
+ .jhcr_assert = JH7110_STGRST_ASSERT,
+ .jhcr_status = JH7110_STGRST_STATUS,
+};
+
+static struct jh7110_reset_config jh7110_isprst_config = {
+ .jhcr_nresets = JH7110_ISPRST_NRESETS,
+ .jhcr_assert = JH7110_ISPRST_ASSERT,
+ .jhcr_status = JH7110_ISPRST_STATUS,
+};
+
+static struct jh7110_reset_config jh7110_voutrst_config = {
+ .jhcr_nresets = JH7110_VOUTRST_NRESETS,
+ .jhcr_assert = JH7110_VOUTRST_ASSERT,
+ .jhcr_status = JH7110_VOUTRST_STATUS,
+};
+
struct jh7110_crg {
const char *jhc_name;
struct jh7110_clock_config *jhc_clk;
+ struct jh7110_reset_config *jhc_rst;
bool jhc_debug;
};
@@ -851,6 +908,7 @@ struct jh7110_crg {
static struct jh7110_crg jh7110_sys_config = {
.jhc_name = "System",
.jhc_clk = &jh7110_sysclk_config,
+ .jhc_rst = &jh7110_sysrst_config,
.jhc_debug = true,
};
@@ -858,22 +916,26 @@ static struct jh7110_crg jh7110_sys_conf
static struct jh7110_crg jh7110_aon_config = {
.jhc_name = "Always-On",
.jhc_clk = &jh7110_aonclk_config,
+ .jhc_rst = &jh7110_aonrst_config,
.jhc_debug = true,
};
static struct jh7110_crg jh7110_isp_config = {
.jhc_name = "Image-Signal-Process",
.jhc_clk = &jh7110_ispclk_config,
+ .jhc_rst = &jh7110_isprst_config,
};
static struct jh7110_crg jh7110_stg_config = {
.jhc_name = "System-Top-Group",
.jhc_clk = &jh7110_stgclk_config,
+ .jhc_rst = &jh7110_stgrst_config,
};
static struct jh7110_crg jh7110_vout_config = {
.jhc_name = "Video Output",
.jhc_clk = &jh7110_voutclk_config,
+ .jhc_rst = &jh7110_voutrst_config,
};
@@ -886,11 +948,108 @@ static const struct device_compatible_en
DEVICE_COMPAT_EOL
};
+#define CLK_LOCK(sc) \
+ mutex_enter(&sc->sc_lock);
+#define CLK_UNLOCK(sc) \
+ mutex_exit(&sc->sc_lock);
+
#define RD4(sc, reg) \
bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
#define WR4(sc, reg, val) \
bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
+#define JH7110_RESET_RETRIES 1000
+
+static void *
+jh7110_clkc_reset_acquire(device_t dev, const void *data, size_t len)
+{
+ struct jh71x0_clkc_softc * const sc = device_private(dev);
+
+ if (len != sizeof(uint32_t))
+ return NULL;
+
+ const uint32_t reset_id = be32dec(data);
+ if (reset_id >= sc->sc_nrsts)
+ return NULL;
+
+ uint32_t *reset = kmem_alloc(sizeof(uint32_t), KM_SLEEP);
+ *reset = reset_id;
+
+ return reset;
+}
+
+static void
+jh7110_clkc_reset_release(device_t dev, void *priv)
+{
+
+ kmem_free(priv, sizeof(uint32_t));
+}
+
+static int
+jh7110_clkc_reset_set(struct jh71x0_clkc_softc *sc, unsigned reset_id,
+ bool assert)
+{
+ const uint32_t off = (reset_id / 32) * sizeof(uint32_t);
+ const uint32_t bit = reset_id % 32;
+ const bus_size_t assert_reg = sc->sc_reset_assert + off;
+ const bus_size_t status_reg = sc->sc_reset_status + off;
+
+ CLK_LOCK(sc);
+
+ const uint32_t val = RD4(sc, assert_reg);
+ if (assert)
+ WR4(sc, assert_reg, val | __BIT(bit));
+ else
+ WR4(sc, assert_reg, val & ~__BIT(bit));
+
+ unsigned i;
+ uint32_t status;
+ for (i = 0; i < JH7110_RESET_RETRIES; i++) {
+ status = RD4(sc, status_reg);
+ bool asserted = (status & __BIT(bit)) == 0;
+ if (asserted == assert)
+ break;
+ }
+ CLK_UNLOCK(sc);
+
+ if (i >= JH7110_RESET_RETRIES) {
+ printf("%s: reset %3d status %#010x / %2d didn't %sassert\n",
+ __func__, reset_id, status, bit, assert ? "" : "de");
+ return ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int
+jh7110_clkc_reset_assert(device_t dev, void *priv)
+{
+ struct jh71x0_clkc_softc * const sc = device_private(dev);
+ const uint32_t *reset = priv;
+ const uint32_t reset_id = *reset;
+
+ return jh7110_clkc_reset_set(sc, reset_id, true);
+}
+
+static int
+jh7110_clkc_reset_deassert(device_t dev, void *priv)
+{
+ struct jh71x0_clkc_softc * const sc = device_private(dev);
+ const uint32_t *reset = priv;
+ const uint32_t reset_id = *reset;
+
+ return jh7110_clkc_reset_set(sc, reset_id, false);
+}
+
+
+static const struct fdtbus_reset_controller_func jh7110_clkc_fdtreset_funcs = {
+ .acquire = jh7110_clkc_reset_acquire,
+ .release = jh7110_clkc_reset_release,
+ .reset_assert = jh7110_clkc_reset_assert,
+ .reset_deassert = jh7110_clkc_reset_deassert,
+};
+
+
static struct clk *
jh7110_clkc_clock_decode(device_t dev, int phandle, const void *data,
size_t len)
@@ -954,9 +1113,15 @@ jh7110_clkc_attach(device_t parent, devi
KASSERT(jhc != NULL);
struct jh7110_clock_config * const jhcc = jhc->jhc_clk;
+ struct jh7110_reset_config * const jhcr = jhc->jhc_rst;
sc->sc_clk = jhcc->jhcc_clocks;
sc->sc_nclks = jhcc->jhcc_nclks;
+ mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
+ sc->sc_nrsts = jhcr->jhcr_nresets;
+ sc->sc_reset_assert = jhcr->jhcr_assert;
+ sc->sc_reset_status = jhcr->jhcr_status;
+
for (size_t id = 0; id < sc->sc_nclks; id++) {
if (sc->sc_clk[id].jcc_type == JH71X0CLK_UNKNOWN)
continue;
@@ -983,6 +1148,7 @@ jh7110_clkc_attach(device_t parent, devi
}
fdtbus_register_clock_controller(self, phandle, &jh7110_clkc_fdtclock_funcs);
+ fdtbus_register_reset_controller(self, phandle, &jh7110_clkc_fdtreset_funcs);
}
CFATTACH_DECL_NEW(jh7110_clkc, sizeof(struct jh71x0_clkc_softc),
Index: src/sys/arch/riscv/starfive/jh71x0_clkc.h
diff -u src/sys/arch/riscv/starfive/jh71x0_clkc.h:1.3 src/sys/arch/riscv/starfive/jh71x0_clkc.h:1.4
--- src/sys/arch/riscv/starfive/jh71x0_clkc.h:1.3 Sun Aug 25 15:23:29 2024
+++ src/sys/arch/riscv/starfive/jh71x0_clkc.h Wed Sep 18 10:37:03 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: jh71x0_clkc.h,v 1.3 2024/08/25 15:23:29 skrll Exp $ */
+/* $NetBSD: jh71x0_clkc.h,v 1.4 2024/09/18 10:37:03 skrll Exp $ */
/*-
* Copyright (c) 2023 The NetBSD Foundation, Inc.
@@ -69,6 +69,8 @@ struct jh71x0_clkc_softc {
size_t sc_nrsts;
bus_size_t sc_reset_assert;
bus_size_t sc_reset_status;
+
+ kmutex_t sc_lock;
};
struct jh71x0_clkc_clk;