Page MenuHomeFreeBSD

D27831.diff
No OneTemporary

D27831.diff

diff --git a/sys/arm64/rockchip/clk/rk3328_cru.c b/sys/arm64/rockchip/clk/rk3328_cru.c
--- a/sys/arm64/rockchip/clk/rk3328_cru.c
+++ b/sys/arm64/rockchip/clk/rk3328_cru.c
@@ -56,6 +56,11 @@
/* 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 @@
#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 @@
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 @@
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 @@
/* 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 @@
.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 @@
.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
--- a/sys/arm64/rockchip/clk/rk3399_cru.c
+++ b/sys/arm64/rockchip/clk/rk3399_cru.c
@@ -964,19 +964,19 @@
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.h b/sys/arm64/rockchip/clk/rk_clk_fract.h
--- 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_fract.c b/sys/arm64/rockchip/clk/rk_clk_fract.c
--- a/sys/arm64/rockchip/clk/rk_clk_fract.c
+++ b/sys/arm64/rockchip/clk/rk_clk_fract.c
@@ -49,21 +49,27 @@
#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 @@
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 @@
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_mux.h b/sys/arm64/rockchip/clk/rk_clk_mux.h
--- a/sys/arm64/rockchip/clk/rk_clk_mux.h
+++ b/sys/arm64/rockchip/clk/rk_clk_mux.h
@@ -41,6 +41,7 @@
};
#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);
diff --git a/sys/arm64/rockchip/clk/rk_clk_mux.c b/sys/arm64/rockchip/clk/rk_clk_mux.c
--- a/sys/arm64/rockchip/clk/rk_clk_mux.c
+++ b/sys/arm64/rockchip/clk/rk_clk_mux.c
@@ -55,8 +55,17 @@
#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 @@
/* 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 @@
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)
{

File Metadata

Mime Type
text/plain
Expires
Wed, Nov 20, 1:22 AM (22 h, 2 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14727052
Default Alt Text
D27831.diff (13 KB)

Event Timeline