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-main
mailing list