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;

Reply via email to