Module Name:    src
Committed By:   jmcneill
Date:           Sun Nov 17 17:33:17 UTC 2019

Modified Files:
        src/sys/arch/arm/sunxi: sun50i_a64_ccu.c sunxi_ccu_div.c

Log Message:
Add support for A64 I2S clocks.


To generate a diff of this commit:
cvs rdiff -u -r1.13 -r1.14 src/sys/arch/arm/sunxi/sun50i_a64_ccu.c
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/arm/sunxi/sunxi_ccu_div.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/arm/sunxi/sun50i_a64_ccu.c
diff -u src/sys/arch/arm/sunxi/sun50i_a64_ccu.c:1.13 src/sys/arch/arm/sunxi/sun50i_a64_ccu.c:1.14
--- src/sys/arch/arm/sunxi/sun50i_a64_ccu.c:1.13	Mon Jul  1 21:06:47 2019
+++ src/sys/arch/arm/sunxi/sun50i_a64_ccu.c	Sun Nov 17 17:33:17 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: sun50i_a64_ccu.c,v 1.13 2019/07/01 21:06:47 jmcneill Exp $ */
+/* $NetBSD: sun50i_a64_ccu.c,v 1.14 2019/11/17 17:33:17 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca>
@@ -28,7 +28,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(1, "$NetBSD: sun50i_a64_ccu.c,v 1.13 2019/07/01 21:06:47 jmcneill Exp $");
+__KERNEL_RCSID(1, "$NetBSD: sun50i_a64_ccu.c,v 1.14 2019/11/17 17:33:17 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -60,6 +60,9 @@ __KERNEL_RCSID(1, "$NetBSD: sun50i_a64_c
 #define	SDMMC0_CLK_REG		0x088
 #define	SDMMC1_CLK_REG		0x08c
 #define	SDMMC2_CLK_REG		0x090
+#define	I2SPCM0_CLK_REG		0x0b0
+#define	I2SPCM1_CLK_REG		0x0b4
+#define	I2SPCM2_CLK_REG		0x0b8
 #define	USBPHY_CFG_REG		0x0cc
 #define	DRAM_CFG_REG		0x0f4
 #define	MBUS_RST_REG		0x0fc
@@ -154,6 +157,7 @@ static const char *mmc_parents[] = { "ho
 static const char *ths_parents[] = { "hosc", NULL, NULL, NULL };
 static const char *de_parents[] = { "pll_periph0_2x", "pll_de" };
 static const char *hdmi_parents[] = { "pll_video0", "pll_video1" };
+static const char *i2s_parents[] = { "pll_audio_8x", "pll_audio_4x", "pll_audio_2x", "pll_audio" };
 static const char *tcon1_parents[] = { "pll_video0", NULL, "pll_video1", NULL };
 static const char *gpu_parents[] = { "pll_gpu" };
 
@@ -407,6 +411,26 @@ static struct sunxi_ccu_clk sun50i_a64_c
 	SUNXI_CCU_GATE(A64_CLK_HDMI_DDC, "hdmi-ddc", "hosc",
 	    HDMI_SLOW_CLK_REG, 31),
 
+	SUNXI_CCU_DIV_GATE(A64_CLK_I2S0, "i2s0", i2s_parents,
+	    I2SPCM0_CLK_REG,	/* reg */
+	    0,			/* div */
+	    __BITS(17,16),	/* sel */
+	    __BIT(31),		/* enable */
+	    0),
+	SUNXI_CCU_DIV_GATE(A64_CLK_I2S1, "i2s1", i2s_parents,
+	    I2SPCM1_CLK_REG,	/* reg */
+	    0,			/* div */
+	    __BITS(17,16),	/* sel */
+	    __BIT(31),		/* enable */
+	    0),
+	SUNXI_CCU_DIV_GATE(A64_CLK_I2S2, "i2s2", i2s_parents,
+	    I2SPCM2_CLK_REG,	/* reg */
+	    0,			/* div */
+	    __BITS(17,16),	/* sel */
+	    __BIT(31),		/* enable */
+	    0),
+
+
 	SUNXI_CCU_DIV_GATE(A64_CLK_TCON1, "tcon1", tcon1_parents,
 	    TCON1_CLK_REG,	/* reg */
 	    __BITS(3,0),	/* div */

Index: src/sys/arch/arm/sunxi/sunxi_ccu_div.c
diff -u src/sys/arch/arm/sunxi/sunxi_ccu_div.c:1.5 src/sys/arch/arm/sunxi/sunxi_ccu_div.c:1.6
--- src/sys/arch/arm/sunxi/sunxi_ccu_div.c:1.5	Mon Mar 19 16:19:17 2018
+++ src/sys/arch/arm/sunxi/sunxi_ccu_div.c	Sun Nov 17 17:33:17 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_ccu_div.c,v 1.5 2018/03/19 16:19:17 bouyer Exp $ */
+/* $NetBSD: sunxi_ccu_div.c,v 1.6 2019/11/17 17:33:17 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_ccu_div.c,v 1.5 2018/03/19 16:19:17 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_ccu_div.c,v 1.6 2019/11/17 17:33:17 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -98,6 +98,38 @@ sunxi_ccu_div_get_rate(struct sunxi_ccu_
 	return rate / ratio;
 }
 
+static int
+sunxi_ccu_div_select_parent(struct sunxi_ccu_softc *sc,
+    struct sunxi_ccu_clk *clk, u_int new_rate)
+{
+	struct sunxi_ccu_div *div = &clk->u.div;
+	struct sunxi_ccu_clk *clk_parent;
+	struct clk *best_parent;
+	u_int index, best_diff;
+	const char *pname;
+
+	best_parent = NULL;
+	best_diff = ~0u;
+	for (index = 0; index < div->nparents; index++) {
+		pname = div->parents[index];
+		if (pname == NULL)
+			continue;
+		clk_parent = sunxi_ccu_clock_find(sc, pname);
+		if (clk_parent == NULL)
+			continue;
+		const u_int rate = clk_get_rate(&clk_parent->base);
+		const u_int diff = abs((int)rate - (int)new_rate);
+		if (diff < best_diff) {
+			best_diff = diff;
+			best_parent = &clk_parent->base;
+		}
+	}
+	if (best_diff == ~0u)
+		return EINVAL;
+
+	return clk_set_parent(&clk->base, best_parent);
+}
+
 int
 sunxi_ccu_div_set_rate(struct sunxi_ccu_softc *sc,
     struct sunxi_ccu_clk *clk, u_int new_rate)
@@ -119,7 +151,7 @@ sunxi_ccu_div_set_rate(struct sunxi_ccu_
 		if ((div->flags & SUNXI_CCU_DIV_SET_RATE_PARENT) != 0)
 			return clk_set_rate(clkp_parent, new_rate);
 		else
-			return ENXIO;
+			return sunxi_ccu_div_select_parent(sc, clk, new_rate);
 	}
 
 	val = CCU_READ(sc, div->reg);

Reply via email to