git: 1547924e5377 - stable/13 - arm64: rockchip: clk_mux: Add support for mux in GRF type clock

From: Emmanuel Vadot <manu_at_FreeBSD.org>
Date: Mon, 16 May 2022 15:33:32 UTC
The branch stable/13 has been updated by manu:

URL: https://cgit.FreeBSD.org/src/commit/?id=1547924e537772d2b6a5bb76375c1739deeaccc5

commit 1547924e537772d2b6a5bb76375c1739deeaccc5
Author:     Emmanuel Vadot <manu@FreeBSD.org>
AuthorDate: 2021-09-09 16:24:33 +0000
Commit:     Emmanuel Vadot <manu@FreeBSD.org>
CommitDate: 2022-05-16 15:27:23 +0000

    arm64: rockchip: clk_mux: Add support for mux in GRF type clock
    
    Some clocks have their mux register in the GRF and not in the CRU.
    Add support for that in the rk_clk_mux clock type.
    
    (cherry picked from commit 731e418bd748f6602bb184ca3a35bab8af241cf1)
---
 sys/arm64/rockchip/clk/rk_clk_mux.c | 50 ++++++++++++++++++++++++++++++++++---
 sys/arm64/rockchip/clk/rk_clk_mux.h |  1 +
 sys/arm64/rockchip/clk/rk_cru.h     | 17 +++++++++++++
 3 files changed, 64 insertions(+), 4 deletions(-)

diff --git a/sys/arm64/rockchip/clk/rk_clk_mux.c b/sys/arm64/rockchip/clk/rk_clk_mux.c
index eb3cdeb99f4b..20e612b8c764 100644
--- a/sys/arm64/rockchip/clk/rk_clk_mux.c
+++ b/sys/arm64/rockchip/clk/rk_clk_mux.c
@@ -38,11 +38,13 @@ __FBSDID("$FreeBSD$");
 #include <machine/bus.h>
 
 #include <dev/extres/clk/clk.h>
+#include <dev/extres/syscon/syscon.h>
 
 #include <arm64/rockchip/clk/rk_cru.h>
 #include <arm64/rockchip/clk/rk_clk_mux.h>
 
 #include "clkdev_if.h"
+#include "syscon_if.h"
 
 #define	WR4(_clk, off, val)						\
 	CLKDEV_WRITE_4(clknode_get_device(_clk), off, val)
@@ -72,6 +74,7 @@ struct rk_clk_mux_sc {
 	uint32_t	shift;
 	uint32_t	mask;
 	int		mux_flags;
+	struct syscon	*grf;
 };
 
 static clknode_method_t rk_clk_mux_methods[] = {
@@ -84,6 +87,25 @@ static clknode_method_t rk_clk_mux_methods[] = {
 DEFINE_CLASS_1(rk_clk_mux, rk_clk_mux_class, rk_clk_mux_methods,
    sizeof(struct rk_clk_mux_sc), clknode_class);
 
+static struct syscon *
+rk_clk_mux_get_grf(struct clknode *clk)
+{
+	device_t dev;
+	phandle_t node;
+	struct syscon *grf;
+
+	grf = NULL;
+	dev = clknode_get_device(clk);
+	node = ofw_bus_get_node(dev);
+	if (OF_hasprop(node, "rockchip,grf") &&
+	    syscon_get_by_ofw_property(dev, node,
+	    "rockchip,grf", &grf) != 0) {
+		return (NULL);
+	}
+
+	return (grf);
+}
+
 static int
 rk_clk_mux_init(struct clknode *clk, device_t dev)
 {
@@ -93,8 +115,19 @@ rk_clk_mux_init(struct clknode *clk, device_t dev)
 
 	sc = clknode_get_softc(clk);
 
+	if ((sc->mux_flags & RK_CLK_MUX_GRF) != 0) {
+		sc->grf = rk_clk_mux_get_grf(clk);
+		if (sc->grf == NULL)
+			panic("clock %s has GRF flag set but no syscon is available",
+			    clknode_get_name(clk));
+	}
+
 	DEVICE_LOCK(clk);
-	rv = RD4(clk, sc->offset, &reg);
+	if (sc->grf) {
+		reg = SYSCON_READ_4(sc->grf, sc->offset);
+		rv = 0;
+	} else
+		rv = RD4(clk, sc->offset, &reg);
 	DEVICE_UNLOCK(clk);
 	if (rv != 0) {
 		return (rv);
@@ -114,13 +147,18 @@ rk_clk_mux_set_mux(struct clknode *clk, int idx)
 	sc = clknode_get_softc(clk);
 
 	DEVICE_LOCK(clk);
-	rv = MD4(clk, sc->offset, sc->mask << sc->shift,
-	    ((idx & sc->mask) << sc->shift) | RK_CLK_MUX_MASK);
+	if (sc->grf)
+		rv = SYSCON_MODIFY_4(sc->grf, sc->offset, sc->mask << sc->shift,
+		  ((idx & sc->mask) << sc->shift) | RK_CLK_MUX_MASK);
+	else
+		rv = MD4(clk, sc->offset, sc->mask << sc->shift,
+		  ((idx & sc->mask) << sc->shift) | RK_CLK_MUX_MASK);
 	if (rv != 0) {
 		DEVICE_UNLOCK(clk);
 		return (rv);
 	}
-	RD4(clk, sc->offset, &reg);
+	if (sc->grf == NULL)
+		RD4(clk, sc->offset, &reg);
 	DEVICE_UNLOCK(clk);
 
 	return(0);
@@ -138,6 +176,10 @@ rk_clk_mux_set_freq(struct clknode *clk, uint64_t fparent, uint64_t *fout,
 
 	sc = clknode_get_softc(clk);
 
+	if ((sc->mux_flags & RK_CLK_MUX_GRF) != 0) {
+		*stop = 1;
+		return (ENOTSUP);
+	}
 	if ((sc->mux_flags & RK_CLK_MUX_REPARENT) == 0) {
 		*stop = 0;
 		return (0);
diff --git a/sys/arm64/rockchip/clk/rk_clk_mux.h b/sys/arm64/rockchip/clk/rk_clk_mux.h
index 7825f8892ac3..c2b5f9cdad69 100644
--- a/sys/arm64/rockchip/clk/rk_clk_mux.h
+++ b/sys/arm64/rockchip/clk/rk_clk_mux.h
@@ -42,6 +42,7 @@ struct rk_clk_mux_def {
 
 #define	RK_CLK_MUX_MASK		0xFFFF0000
 #define	RK_CLK_MUX_REPARENT	(1 << 0)
+#define	RK_CLK_MUX_GRF		(1 << 1)
 
 int rk_clk_mux_register(struct clkdom *clkdom, struct rk_clk_mux_def *clkdef);
 
diff --git a/sys/arm64/rockchip/clk/rk_cru.h b/sys/arm64/rockchip/clk/rk_cru.h
index 0d1c49f01290..1c749d1d2c87 100644
--- a/sys/arm64/rockchip/clk/rk_cru.h
+++ b/sys/arm64/rockchip/clk/rk_cru.h
@@ -186,6 +186,23 @@
 	},								\
 }
 
+/* Complex clock without divider (multiplexer only in GRF). */
+#define MUXGRF(_id, _name, _pn, _f,  _mo, _ms, _mw)			\
+{									\
+	.type = RK_CLK_MUX,						\
+	.clk.mux = &(struct rk_clk_mux_def) {				\
+		.clkdef.id = _id,					\
+		.clkdef.name = _name,					\
+		.clkdef.parent_names = _pn,				\
+		.clkdef.parent_cnt = nitems(_pn),			\
+		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
+		.offset = _mo,						\
+		.shift = _ms,						\
+		.width = _mw,						\
+		.mux_flags = RK_CLK_MUX_GRF | _f,			\
+	},								\
+}
+
 struct rk_cru_gate {
 	const char	*name;
 	const char	*parent_name;