git: f0a5e81af436 - main - arm64: rockchip, implement the two rk805/808 clocks

Bjoern A. Zeeb bz at FreeBSD.org
Wed May 19 12:14:18 UTC 2021


The branch main has been updated by bz:

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

commit f0a5e81af4361abfc09ccaefbc375ece35ff79cc
Author:     Bjoern A. Zeeb <bz at FreeBSD.org>
AuthorDate: 2021-05-06 14:25:52 +0000
Commit:     Bjoern A. Zeeb <bz at FreeBSD.org>
CommitDate: 2021-05-19 11:48:11 +0000

    arm64: rockchip, implement the two rk805/808 clocks
    
    While the xin32k clk was implemented in rk3399_cru as a fixed rate
    clock, migrate it to rk805 as we will also need the 2nd clock
    'rtc_clko_wifi' for SDIO and BT.
    Both clocks remain fixed rate, and while the 1st one is always on
    (though that is not expressed in the clk framework), the 2nd one
    we can toggle on/off.
    
    Reviewed-by:    manu
    Tested-by:      manu
    MFC-after:      2 weeks
    Differential Revision:  https://reviews.freebsd.org/D26870
---
 sys/arm64/rockchip/clk/rk3399_cru.c |   2 +-
 sys/arm64/rockchip/rk805.c          | 122 +++++++++++++++++++++++++++++++++++-
 2 files changed, 120 insertions(+), 4 deletions(-)

diff --git a/sys/arm64/rockchip/clk/rk3399_cru.c b/sys/arm64/rockchip/clk/rk3399_cru.c
index 595085862e13..585f6d4c33b9 100644
--- a/sys/arm64/rockchip/clk/rk3399_cru.c
+++ b/sys/arm64/rockchip/clk/rk3399_cru.c
@@ -775,7 +775,7 @@ PLIST(uart3_p)= {"clk_uart3_div", "clk_uart3_frac", "xin24m"};
 static struct rk_clk rk3399_clks[] = {
 	/* External clocks */
 	LINK("xin24m"),
-	FRATE(0, "xin32k", 32768),
+	LINK("xin32k"),
 	FFACT(0, "xin12m", "xin24m", 1, 2),
 	FRATE(0, "clkin_i2s", 0),
 	FRATE(0, "pclkin_cif", 0),
diff --git a/sys/arm64/rockchip/rk805.c b/sys/arm64/rockchip/rk805.c
index d3e04081aeb2..2d5635fee72a 100644
--- a/sys/arm64/rockchip/rk805.c
+++ b/sys/arm64/rockchip/rk805.c
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
 #include <dev/ofw/ofw_bus.h>
 #include <dev/ofw/ofw_bus_subr.h>
 
+#include <dev/extres/clk/clk.h>
 #include <dev/extres/regulator/regulator.h>
 
 #include <arm64/rockchip/rk805reg.h>
@@ -584,6 +585,118 @@ rk805_reg_attach(device_t dev, phandle_t node,
 	return (reg_sc);
 }
 
+/* -------------------------------------------------------------------------- */
+
+/* Clock class and method */
+struct rk805_clk_sc {
+	device_t		base_dev;
+};
+
+#define	CLK32OUT_REG		0x20
+#define	CLK32OUT_CLKOUT2_EN	1
+
+static int
+rk805_clk_set_gate_1(struct clknode *clk, bool enable)
+{
+	struct rk805_clk_sc *sc;
+	uint8_t val;
+
+	sc = clknode_get_softc(clk);
+
+	rk805_read(sc->base_dev, CLK32OUT_REG, &val, sizeof(val));
+	if (enable)
+		val |= CLK32OUT_CLKOUT2_EN;
+	else
+		val &= ~CLK32OUT_CLKOUT2_EN;
+	rk805_write(sc->base_dev, CLK32OUT_REG, &val, 1);
+
+	return (0);
+}
+
+static int
+rk805_clk_recalc(struct clknode *clk, uint64_t *freq)
+{
+
+	*freq = 32768;
+	return (0);
+}
+
+static clknode_method_t rk805_clk_clknode_methods_0[] = {
+	CLKNODEMETHOD(clknode_recalc_freq,	rk805_clk_recalc),
+	CLKNODEMETHOD_END
+};
+
+DEFINE_CLASS_1(rk805_clk_clknode_0, rk805_clk_clknode_class_0,
+    rk805_clk_clknode_methods_0, sizeof(struct rk805_clk_sc),
+    clknode_class);
+
+static clknode_method_t rk805_clk_clknode_methods_1[] = {
+	CLKNODEMETHOD(clknode_set_gate,		rk805_clk_set_gate_1),
+	CLKNODEMETHOD_END
+};
+
+DEFINE_CLASS_1(rk805_clk_clknode_1, rk805_clk_clknode_class_1,
+    rk805_clk_clknode_methods_1, sizeof(struct rk805_clk_sc),
+    rk805_clk_clknode_class_0);
+
+static int
+rk805_export_clocks(device_t dev)
+{
+	struct clkdom *clkdom;
+	struct clknode_init_def clkidef;
+	struct clknode *clk;
+	struct rk805_clk_sc *clksc;
+	const char **clknames;
+	phandle_t node;
+	int nclks, rv;
+
+	node = ofw_bus_get_node(dev);
+
+	/* clock-output-names are optional. Could use them for clkidef.name. */
+	nclks = ofw_bus_string_list_to_array(node, "clock-output-names",
+	    &clknames);
+
+	clkdom = clkdom_create(dev);
+
+	memset(&clkidef, 0, sizeof(clkidef));
+	clkidef.id = 0;
+	clkidef.name = (nclks = 2) ? clknames[0] : "clk32kout1";
+	clk = clknode_create(clkdom, &rk805_clk_clknode_class_0, &clkidef);
+	if (clk == NULL) {
+		device_printf(dev, "Cannot create '%s'.\n", clkidef.name);
+		return (ENXIO);
+	}
+	clksc = clknode_get_softc(clk);
+	clksc->base_dev = dev;
+	clknode_register(clkdom, clk);
+
+	memset(&clkidef, 0, sizeof(clkidef));
+	clkidef.id = 1;
+	clkidef.name = (nclks = 2) ? clknames[1] : "clk32kout2";
+	clk = clknode_create(clkdom, &rk805_clk_clknode_class_1, &clkidef);
+	if (clk == NULL) {
+		device_printf(dev, "Cannot create '%s'.\n", clkidef.name);
+		return (ENXIO);
+	}
+	clksc = clknode_get_softc(clk);
+	clksc->base_dev = dev;
+	clknode_register(clkdom, clk);
+
+	rv = clkdom_finit(clkdom);
+	if (rv != 0) {
+		device_printf(dev, "Cannot finalize clkdom initialization: "
+		    "%d\n", rv);
+		return (ENXIO);
+	}
+
+	if (bootverbose)
+		clkdom_dump(clkdom);
+
+	return (0);
+}
+
+/* -------------------------------------------------------------------------- */
+
 static int
 rk805_probe(device_t dev)
 {
@@ -745,17 +858,20 @@ rk805_attach(device_t dev)
 	struct rk805_regdef *regdefs;
 	struct reg_list *regp;
 	phandle_t rnode, child;
-	int i;
+	int error, i;
 
 	sc = device_get_softc(dev);
 
+	sc->type = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
+	error = rk805_export_clocks(dev);
+	if (error != 0)
+		return (error);
+
 	sc->intr_hook.ich_func = rk805_start;
 	sc->intr_hook.ich_arg = dev;
-
 	if (config_intrhook_establish(&sc->intr_hook) != 0)
 		return (ENOMEM);
 
-	sc->type = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
 	switch (sc->type) {
 	case RK805:
 		regdefs = rk805_regdefs;


More information about the dev-commits-src-all mailing list