aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmmanuel Vadot <manu@FreeBSD.org>2021-09-09 16:24:33 +0000
committerEmmanuel Vadot <manu@FreeBSD.org>2021-09-15 16:43:04 +0000
commit731e418bd748f6602bb184ca3a35bab8af241cf1 (patch)
tree94af8e75f87a11d24209c8ed4d3757856ea6650c
parente3e7d953323c450dbe3ecbb21f9741f049ee3017 (diff)
downloadsrc-731e418bd748f6602bb184ca3a35bab8af241cf1.tar.gz
src-731e418bd748f6602bb184ca3a35bab8af241cf1.zip
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.
-rw-r--r--sys/arm64/rockchip/clk/rk_clk_mux.c50
-rw-r--r--sys/arm64/rockchip/clk/rk_clk_mux.h1
-rw-r--r--sys/arm64/rockchip/clk/rk_cru.h17
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;