The branch main has been updated by gonzo:

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

commit d03fd8ede2c493d0c5a74b625a93a48e018515e1
Author:     Oleksandr Tymoshenko <go...@freebsd.org>
AuthorDate: 2020-12-30 00:25:52 +0000
Commit:     Oleksandr Tymoshenko <go...@freebsd.org>
CommitDate: 2021-01-04 00:50:42 +0000

    rockchip: add audio-related clocks to the CRU driver
    
    - Add I2S and CODEC clocks to CRU driver
    - Add support for gate selection to frac clock
    - Add setfreq support to mux clock
    
    Reviewed by:    manu
    Differential Revision:  https://reviews.freebsd.org/D27831
---
 sys/arm64/rockchip/clk/rk3328_cru.c   | 275 ++++++++++++++++++++++++++++++++++
 sys/arm64/rockchip/clk/rk3399_cru.c   |   6 +-
 sys/arm64/rockchip/clk/rk_clk_fract.c |  35 +++++
 sys/arm64/rockchip/clk/rk_clk_fract.h |   4 +
 sys/arm64/rockchip/clk/rk_clk_mux.c   |  61 ++++++++
 sys/arm64/rockchip/clk/rk_clk_mux.h   |   1 +
 6 files changed, 379 insertions(+), 3 deletions(-)

diff --git a/sys/arm64/rockchip/clk/rk3328_cru.c 
b/sys/arm64/rockchip/clk/rk3328_cru.c
index 69ad2dac873c..e110564f773d 100644
--- a/sys/arm64/rockchip/clk/rk3328_cru.c
+++ b/sys/arm64/rockchip/clk/rk3328_cru.c
@@ -56,6 +56,11 @@ __FBSDID("$FreeBSD$");
 
 /* GATES */
 
+#define        SCLK_I2S0               41
+#define        SCLK_I2S1               42
+#define        SCLK_I2S2               43
+#define        SCLK_I2S1_OUT           44
+#define        SCLK_I2S2_OUT           45
 #define        SCLK_MAC2PHY_RXTX       83
 #define        SCLK_MAC2PHY_SRC        84
 #define        SCLK_MAC2PHY_REF        85
@@ -90,6 +95,10 @@ __FBSDID("$FreeBSD$");
 #define        PCLK_USB3PHY_OTG        224
 #define        PCLK_USB3PHY_PIPE       225
 #define        PCLK_USB3_GRF           226
+#define        PCLK_ACODECPHY          235
+#define        HCLK_I2S0_8CH           311
+#define        HCLK_I2S1_8CH           312
+#define        HCLK_I2S2_2CH           313
 #define        HCLK_SDMMC              317
 #define        HCLK_SDIO               318
 #define        HCLK_EMMC               319
@@ -102,6 +111,11 @@ static struct rk_cru_gate rk3328_gates[] = {
        CRU_GATE(0, "gpll_core", "gpll", 0x200, 2)
        CRU_GATE(0, "npll_core", "npll", 0x200, 12)
 
+       /* CRU_CLKGATE_CON1 */
+       CRU_GATE(SCLK_I2S0, "clk_i2s0", "clk_i2s0_mux", 0x204, 3)
+       CRU_GATE(SCLK_I2S1, "clk_i2s1", "clk_i2s1_mux", 0x204, 6)
+       CRU_GATE(SCLK_I2S1, "clk_i2s2", "clk_i2s2_mux", 0x204, 10)
+
        /* CRU_CLKGATE_CON4 */
        CRU_GATE(0, "gpll_peri", "gpll", 0x210, 0)
        CRU_GATE(0, "cpll_peri", "cpll", 0x210, 1)
@@ -123,6 +137,9 @@ static struct rk_cru_gate rk3328_gates[] = {
        CRU_GATE(ACLK_PERI, "aclk_peri", "aclk_peri_pre", 0x228, 0)
 
        /* CRU_CLKGATE_CON15*/
+       CRU_GATE(HCLK_I2S0_8CH, "hclk_i2s0_8ch", "hclk_bus_pre", 0x23C, 3)
+       CRU_GATE(HCLK_I2S1_8CH, "hclk_i2s1_8ch", "hclk_bus_pre", 0x23C, 4)
+       CRU_GATE(HCLK_I2S2_2CH, "hclk_i2s2_2ch", "hclk_bus_pre", 0x23C, 5)
        CRU_GATE(PCLK_I2C0, "pclk_i2c0", "pclk_bus", 0x23C, 10)
 
        /* CRU_CLKGATE_CON16 */
@@ -138,6 +155,7 @@ static struct rk_cru_gate rk3328_gates[] = {
 
        /* CRU_CLKGATE_CON17 */
        CRU_GATE(PCLK_USB3_GRF, "pclk_usb3_grf", "pclk_phy_pre", 0x244, 2)
+       CRU_GATE(PCLK_ACODECPHY, "pclk_acodecphy", "pclk_phy_pre", 0x244, 5)
 
        /* CRU_CLKGATE_CON19 */
        CRU_GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", 0x24C, 0)
@@ -1115,6 +1133,215 @@ static struct rk_clk_composite_def ref_usb3otg_src = {
        .flags = RK_CLK_COMPOSITE_HAVE_GATE,
 };
 
+/* I2S0 */
+static const char *i2s0_div_parents[] = { "cpll", "gpll" };
+static struct rk_clk_composite_def i2s0_div = {
+       .clkdef = {
+               .id = 0,
+               .name = "clk_i2s0_div",
+               .parent_names = i2s0_div_parents,
+               .parent_cnt = nitems(i2s0_div_parents),
+       },
+       /* CRU_CLKSEL_CON6 */
+       .muxdiv_offset = 0x118,
+
+       .mux_shift = 15,
+       .mux_width = 1,
+
+       .div_shift = 0,
+       .div_width = 7,
+
+       /* CRU_CLKGATE_CON1 */
+       .gate_offset = 0x204,
+       .gate_shift = 1,
+
+       .flags = RK_CLK_COMPOSITE_HAVE_GATE,
+};
+
+static const char *i2s0_frac_parents[] = { "clk_i2s0_div" };
+static struct rk_clk_fract_def i2s0_frac = {
+       .clkdef = {
+               .id = 0,
+               .name = "clk_i2s0_frac",
+               .parent_names = i2s0_frac_parents,
+               .parent_cnt = nitems(i2s0_frac_parents),
+       },
+       /* CRU_CLKSEL_CON7 */
+       .offset = 0x11c,
+
+       /* CRU_CLKGATE_CON1 */
+       .gate_offset = 0x204,
+       .gate_shift = 2,
+
+       .flags = RK_CLK_FRACT_HAVE_GATE,
+};
+
+static const char *i2s0_mux_parents[] = { "clk_i2s0_div", "clk_i2s0_frac", 
"xin12m", "xin12m" };
+static struct rk_clk_mux_def i2s0_mux = {
+       .clkdef = {
+               .id = 0,
+               .name = "clk_i2s0_mux",
+               .parent_names = i2s0_mux_parents,
+               .parent_cnt = nitems(i2s0_mux_parents),
+       },
+       .offset = 0x118,
+
+       .shift = 8,
+       .width = 2,
+
+       .mux_flags = RK_CLK_MUX_REPARENT,
+};
+
+/* I2S1 */
+static const char *i2s1_div_parents[] = { "cpll", "gpll" };
+static struct rk_clk_composite_def i2s1_div = {
+       .clkdef = {
+               .id = 0,
+               .name = "clk_i2s1_div",
+               .parent_names = i2s1_div_parents,
+               .parent_cnt = nitems(i2s1_div_parents),
+       },
+       /* CRU_CLKSEL_CON8 */
+       .muxdiv_offset = 0x120,
+
+       .mux_shift = 15,
+       .mux_width = 1,
+
+       .div_shift = 0,
+       .div_width = 7,
+
+       /* CRU_CLKGATE_CON1 */
+       .gate_offset = 0x204,
+       .gate_shift = 4,
+
+       .flags = RK_CLK_COMPOSITE_HAVE_GATE,
+};
+
+static const char *i2s1_frac_parents[] = { "clk_i2s1_div" };
+static struct rk_clk_fract_def i2s1_frac = {
+       .clkdef = {
+               .id = 0,
+               .name = "clk_i2s1_frac",
+               .parent_names = i2s1_frac_parents,
+               .parent_cnt = nitems(i2s1_frac_parents),
+       },
+       /* CRU_CLKSEL_CON9 */
+       .offset = 0x124,
+
+       /* CRU_CLKGATE_CON1 */
+       .gate_offset = 0x204,
+       .gate_shift = 5,
+
+       .flags = RK_CLK_FRACT_HAVE_GATE,
+};
+
+static const char *i2s1_mux_parents[] = { "clk_i2s1_div", "clk_i2s1_frac", 
"clkin_i2s1", "xin12m" };
+static struct rk_clk_mux_def i2s1_mux = {
+       .clkdef = {
+               .id = 0,
+               .name = "clk_i2s1_mux",
+               .parent_names = i2s1_mux_parents,
+               .parent_cnt = nitems(i2s1_mux_parents),
+       },
+       .offset = 0x120,
+
+       .shift = 8,
+       .width = 2,
+       .mux_flags = RK_CLK_MUX_REPARENT,
+};
+
+static struct clk_fixed_def clkin_i2s1 = {
+       .clkdef = {
+               .id = 0,
+               .name = "clkin_i2s1",
+               .parent_names = NULL,
+               .parent_cnt = 0
+       },
+
+       .freq = 0,
+};
+
+/* I2S2 */
+static const char *i2s2_div_parents[] = { "cpll", "gpll" };
+static struct rk_clk_composite_def i2s2_div = {
+       .clkdef = {
+               .id = 0,
+               .name = "clk_i2s2_div",
+               .parent_names = i2s2_div_parents,
+               .parent_cnt = nitems(i2s2_div_parents),
+       },
+       /* CRU_CLKSEL_CON10 */
+       .muxdiv_offset = 0x128,
+
+       .mux_shift = 15,
+       .mux_width = 1,
+
+       .div_shift = 0,
+       .div_width = 7,
+
+       /* CRU_CLKGATE_CON1 */
+       .gate_offset = 0x204,
+       .gate_shift = 8,
+
+       .flags = RK_CLK_COMPOSITE_HAVE_GATE,
+};
+
+static const char *i2s2_frac_parents[] = { "clk_i2s2_div" };
+static struct rk_clk_fract_def i2s2_frac = {
+       .clkdef = {
+               .id = 0,
+               .name = "clk_i2s2_frac",
+               .parent_names = i2s2_frac_parents,
+               .parent_cnt = nitems(i2s2_frac_parents),
+       },
+       /* CRU_CLKSEL_CON11 */
+       .offset = 0x12c,
+
+       /* CRU_CLKGATE_CON1 */
+       .gate_offset = 0x204,
+       .gate_shift = 9,
+
+       .flags = RK_CLK_FRACT_HAVE_GATE,
+};
+
+static const char *i2s2_mux_parents[] = { "clk_i2s2_div", "clk_i2s2_frac", 
"clkin_i2s2", "xin12m" };
+static struct rk_clk_mux_def i2s2_mux = {
+       .clkdef = {
+               .id = 0,
+               .name = "clk_i2s2_mux",
+               .parent_names = i2s2_mux_parents,
+               .parent_cnt = nitems(i2s2_mux_parents),
+       },
+       .offset = 0x128,
+
+       .shift = 8,
+       .width = 2,
+
+       .mux_flags = RK_CLK_MUX_REPARENT,
+};
+
+static struct clk_fixed_def clkin_i2s2 = {
+       .clkdef = {
+               .id = 0,
+               .name = "clkin_i2s2",
+               .parent_names = NULL,
+               .parent_cnt = 0
+       },
+
+       .freq = 0,
+};
+
+static struct clk_fixed_def xin12m = {
+       .clkdef = {
+               .id = 0,
+               .name = "xin12m",
+               .parent_names = NULL,
+               .parent_cnt = 0
+       },
+
+       .freq = 12000000,
+};
+
 static const char *mac2io_src_parents[] = { "cpll", "gpll" };
 
 static struct rk_clk_composite_def mac2io_src = {
@@ -1417,6 +1644,54 @@ static struct rk_clk rk3328_clks[] = {
                .type = RK_CLK_COMPOSITE,
                .clk.composite = &usb3otg_suspend
        },
+       {
+               .type = RK_CLK_COMPOSITE,
+               .clk.composite = &i2s0_div
+       },
+       {
+               .type = RK_CLK_FRACT,
+               .clk.fract = &i2s0_frac
+       },
+       {
+               .type = RK_CLK_MUX,
+               .clk.mux = &i2s0_mux
+       },
+       {
+               .type = RK_CLK_COMPOSITE,
+               .clk.composite = &i2s1_div
+       },
+       {
+               .type = RK_CLK_FRACT,
+               .clk.fract = &i2s1_frac
+       },
+       {
+               .type = RK_CLK_MUX,
+               .clk.mux = &i2s1_mux
+       },
+       {
+               .type = RK_CLK_FIXED,
+               .clk.fixed = &clkin_i2s1
+       },
+       {
+               .type = RK_CLK_COMPOSITE,
+               .clk.composite = &i2s2_div
+       },
+       {
+               .type = RK_CLK_FRACT,
+               .clk.fract = &i2s2_frac
+       },
+       {
+               .type = RK_CLK_MUX,
+               .clk.mux = &i2s2_mux
+       },
+       {
+               .type = RK_CLK_FIXED,
+               .clk.fixed = &clkin_i2s2
+       },
+       {
+               .type = RK_CLK_FIXED,
+               .clk.fixed = &xin12m
+       },
        {
                .type = RK_CLK_COMPOSITE,
                .clk.composite = &mac2io_src
diff --git a/sys/arm64/rockchip/clk/rk3399_cru.c 
b/sys/arm64/rockchip/clk/rk3399_cru.c
index 77686ecb66b8..595085862e13 100644
--- a/sys/arm64/rockchip/clk/rk3399_cru.c
+++ b/sys/arm64/rockchip/clk/rk3399_cru.c
@@ -964,19 +964,19 @@ static struct rk_clk rk3399_clks[] = {
            27, 0, 10,  15, 1),
 
        /* CRU_CLKSEL_CON28 */
-       MUX(0, "clk_i2s0_mux", i2s0_p, 0,
+       MUX(0, "clk_i2s0_mux", i2s0_p, RK_CLK_MUX_REPARENT,
            28, 8, 2),
        COMP(0, "clk_i2s0_div_c", pll_src_cpll_gpll_p, 0,
            28, 0, 7,   7, 1),
 
        /* CRU_CLKSEL_CON29 */
-       MUX(0, "clk_i2s1_mux", i2s1_p, 0,
+       MUX(0, "clk_i2s1_mux", i2s1_p, RK_CLK_MUX_REPARENT,
            29,         8, 2),
        COMP(0, "clk_i2s1_div_c", pll_src_cpll_gpll_p, 0,
            29, 0, 7,   7, 1),
 
        /* CRU_CLKSEL_CON30 */
-       MUX(0, "clk_i2s2_mux", i2s2_p, 0,
+       MUX(0, "clk_i2s2_mux", i2s2_p, RK_CLK_MUX_REPARENT,
            30,         8, 2),
        COMP(0, "clk_i2s2_div_c", pll_src_cpll_gpll_p, 0,
            30, 0, 7,   7, 1),
diff --git a/sys/arm64/rockchip/clk/rk_clk_fract.c 
b/sys/arm64/rockchip/clk/rk_clk_fract.c
index 9bb4e169fb97..afdf56cfade7 100644
--- a/sys/arm64/rockchip/clk/rk_clk_fract.c
+++ b/sys/arm64/rockchip/clk/rk_clk_fract.c
@@ -49,21 +49,27 @@ __FBSDID("$FreeBSD$");
 #define        DEVICE_UNLOCK(_clk)                                             
\
        CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
 
+#define        RK_CLK_FRACT_MASK_SHIFT 16
+
 static int rk_clk_fract_init(struct clknode *clk, device_t dev);
 static int rk_clk_fract_recalc(struct clknode *clk, uint64_t *req);
 static int rk_clk_fract_set_freq(struct clknode *clknode, uint64_t fin,
     uint64_t *fout, int flag, int *stop);
+static int rk_clk_fract_set_gate(struct clknode *clk, bool enable);
 
 struct rk_clk_fract_sc {
        uint32_t        flags;
        uint32_t        offset;
        uint32_t        numerator;
        uint32_t        denominator;
+       uint32_t        gate_offset;
+       uint32_t        gate_shift;
 };
 
 static clknode_method_t rk_clk_fract_methods[] = {
        /* Device interface */
        CLKNODEMETHOD(clknode_init,             rk_clk_fract_init),
+       CLKNODEMETHOD(clknode_set_gate,         rk_clk_fract_set_gate),
        CLKNODEMETHOD(clknode_recalc_freq,      rk_clk_fract_recalc),
        CLKNODEMETHOD(clknode_set_freq,         rk_clk_fract_set_freq),
        CLKNODEMETHOD_END
@@ -149,6 +155,33 @@ rk_clk_fract_init(struct clknode *clk, device_t dev)
        return(0);
 }
 
+static int
+rk_clk_fract_set_gate(struct clknode *clk, bool enable)
+{
+       struct rk_clk_fract_sc *sc;
+       uint32_t val = 0;
+
+       sc = clknode_get_softc(clk);
+
+       if ((sc->flags & RK_CLK_FRACT_HAVE_GATE) == 0)
+               return (0);
+
+       RD4(clk, sc->gate_offset, &val);
+
+       val = 0;
+       if (!enable)
+               val |= 1 << sc->gate_shift;
+       val |= (1 << sc->gate_shift) << RK_CLK_FRACT_MASK_SHIFT;
+       DEVICE_LOCK(clk);
+       WR4(clk, sc->gate_offset, val);
+       DEVICE_UNLOCK(clk);
+
+       return (0);
+}
+
+static int
+rk_clk_fract_set_freq(struct clknode *clk, uint64_t fin, uint64_t *fout,
+    int flags, int *stop);
 static int
 rk_clk_fract_recalc(struct clknode *clk, uint64_t *freq)
 {
@@ -240,6 +273,8 @@ rk_clk_fract_register(struct clkdom *clkdom, struct 
rk_clk_fract_def *clkdef)
        sc = clknode_get_softc(clk);
        sc->flags = clkdef->flags;
        sc->offset = clkdef->offset;
+       sc->gate_offset = clkdef->gate_offset;
+       sc->gate_shift = clkdef->gate_shift;
 
        clknode_register(clkdom, clk);
        return (0);
diff --git a/sys/arm64/rockchip/clk/rk_clk_fract.h 
b/sys/arm64/rockchip/clk/rk_clk_fract.h
index 2fe8f47586e5..03fab3fd2884 100644
--- a/sys/arm64/rockchip/clk/rk_clk_fract.h
+++ b/sys/arm64/rockchip/clk/rk_clk_fract.h
@@ -35,9 +35,13 @@
 struct rk_clk_fract_def {
        struct clknode_init_def clkdef;
        uint32_t                offset;
+       uint32_t                gate_offset;
+       uint32_t                gate_shift;
        uint32_t                flags;
 };
 
+#define        RK_CLK_FRACT_HAVE_GATE  0x0001
+
 int rk_clk_fract_register(struct clkdom *clkdom,
     struct rk_clk_fract_def *clkdef);
 
diff --git a/sys/arm64/rockchip/clk/rk_clk_mux.c 
b/sys/arm64/rockchip/clk/rk_clk_mux.c
index 94d31d34c47b..2280051b5a0c 100644
--- a/sys/arm64/rockchip/clk/rk_clk_mux.c
+++ b/sys/arm64/rockchip/clk/rk_clk_mux.c
@@ -55,8 +55,17 @@ __FBSDID("$FreeBSD$");
 #define        DEVICE_UNLOCK(_clk)                                             
\
        CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
 
+#if 0
+#define        dprintf(format, arg...)                                         
\
+       printf("%s:(%s)" format, __func__, clknode_get_name(clk), arg)
+#else
+#define        dprintf(format, arg...)
+#endif
+
 static int rk_clk_mux_init(struct clknode *clk, device_t dev);
 static int rk_clk_mux_set_mux(struct clknode *clk, int idx);
+static int rk_clk_mux_set_freq(struct clknode *clk, uint64_t fparent,
+    uint64_t *fout, int flags, int *stop);
 
 struct rk_clk_mux_sc {
        uint32_t        offset;
@@ -69,6 +78,7 @@ static clknode_method_t rk_clk_mux_methods[] = {
        /* Device interface */
        CLKNODEMETHOD(clknode_init,     rk_clk_mux_init),
        CLKNODEMETHOD(clknode_set_mux,  rk_clk_mux_set_mux),
+       CLKNODEMETHOD(clknode_set_freq, rk_clk_mux_set_freq),
        CLKNODEMETHOD_END
 };
 DEFINE_CLASS_1(rk_clk_mux, rk_clk_mux_class, rk_clk_mux_methods,
@@ -116,6 +126,57 @@ rk_clk_mux_set_mux(struct clknode *clk, int idx)
        return(0);
 }
 
+static int
+rk_clk_mux_set_freq(struct clknode *clk, uint64_t fparent, uint64_t *fout,
+    int flags, int *stop)
+{
+       struct rk_clk_mux_sc *sc;
+       struct clknode *p_clk, *p_best_clk;
+       const char **p_names;
+       int p_idx, best_parent;
+       int rv;
+
+       sc = clknode_get_softc(clk);
+
+       if ((sc->mux_flags & RK_CLK_MUX_REPARENT) == 0)
+               return (0);
+
+       dprintf("Finding best parent for target freq of %ju\n", *fout);
+       p_names = clknode_get_parent_names(clk);
+       for (p_idx = 0; p_idx != clknode_get_parents_num(clk); p_idx++) {
+               p_clk = clknode_find_by_name(p_names[p_idx]);
+               dprintf("Testing with parent %s (%d)\n",
+                   clknode_get_name(p_clk), p_idx);
+
+               rv = clknode_set_freq(p_clk, *fout, flags | CLK_SET_DRYRUN, 0);
+               dprintf("Testing with parent %s (%d) rv=%d\n",
+                   clknode_get_name(p_clk), p_idx, rv);
+               if (rv == 0) {
+                       best_parent = p_idx;
+                       p_best_clk = p_clk;
+                       *stop = 1;
+               }
+       }
+
+       if (!*stop)
+               return (0);
+
+       if ((flags & CLK_SET_DRYRUN) != 0)
+               return (0);
+
+       p_idx = clknode_get_parent_idx(clk);
+       if (p_idx != best_parent) {
+               dprintf("Switching parent index from %d to %d\n", p_idx,
+                   best_parent);
+               clknode_set_parent_by_idx(clk, best_parent);
+       }
+
+       clknode_set_freq(p_best_clk, *fout, flags, 0);
+       clknode_get_freq(p_best_clk, fout);
+
+       return (0);
+}
+
 int
 rk_clk_mux_register(struct clkdom *clkdom, struct rk_clk_mux_def *clkdef)
 {
diff --git a/sys/arm64/rockchip/clk/rk_clk_mux.h 
b/sys/arm64/rockchip/clk/rk_clk_mux.h
index f44443790b18..7825f8892ac3 100644
--- a/sys/arm64/rockchip/clk/rk_clk_mux.h
+++ b/sys/arm64/rockchip/clk/rk_clk_mux.h
@@ -41,6 +41,7 @@ struct rk_clk_mux_def {
 };
 
 #define        RK_CLK_MUX_MASK         0xFFFF0000
+#define        RK_CLK_MUX_REPARENT     (1 << 0)
 
 int rk_clk_mux_register(struct clkdom *clkdom, struct rk_clk_mux_def *clkdef);
 
_______________________________________________
dev-commits-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all
To unsubscribe, send any mail to "dev-commits-src-all-unsubscr...@freebsd.org"

Reply via email to