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);