Module Name: src Committed By: jmcneill Date: Mon Jul 17 23:26:17 UTC 2017
Modified Files: src/sys/arch/arm/sunxi: files.sunxi sun8i_h3_ccu.c sunxi_ccu.c sunxi_ccu.h Added Files: src/sys/arch/arm/sunxi: sunxi_ccu_phase.c Log Message: Add SDMMC[012] sample/output clock phase controls. To generate a diff of this commit: cvs rdiff -u -r1.11 -r1.12 src/sys/arch/arm/sunxi/files.sunxi cvs rdiff -u -r1.7 -r1.8 src/sys/arch/arm/sunxi/sun8i_h3_ccu.c cvs rdiff -u -r1.5 -r1.6 src/sys/arch/arm/sunxi/sunxi_ccu.c cvs rdiff -u -r1.6 -r1.7 src/sys/arch/arm/sunxi/sunxi_ccu.h cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/sunxi/sunxi_ccu_phase.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/files.sunxi diff -u src/sys/arch/arm/sunxi/files.sunxi:1.11 src/sys/arch/arm/sunxi/files.sunxi:1.12 --- src/sys/arch/arm/sunxi/files.sunxi:1.11 Sat Jul 8 11:12:24 2017 +++ src/sys/arch/arm/sunxi/files.sunxi Mon Jul 17 23:26:17 2017 @@ -1,4 +1,4 @@ -# $NetBSD: files.sunxi,v 1.11 2017/07/08 11:12:24 jmcneill Exp $ +# $NetBSD: files.sunxi,v 1.12 2017/07/17 23:26:17 jmcneill Exp $ # # Configuration info for Allwinner sunxi family SoCs # @@ -24,6 +24,7 @@ file arch/arm/sunxi/sunxi_ccu_div.c sun file arch/arm/sunxi/sunxi_ccu_gate.c sunxi_ccu file arch/arm/sunxi/sunxi_ccu_nm.c sunxi_ccu file arch/arm/sunxi/sunxi_ccu_nkmp.c sunxi_ccu +file arch/arm/sunxi/sunxi_ccu_phase.c sunxi_ccu file arch/arm/sunxi/sunxi_ccu_prediv.c sunxi_ccu # CCU (A31) Index: src/sys/arch/arm/sunxi/sun8i_h3_ccu.c diff -u src/sys/arch/arm/sunxi/sun8i_h3_ccu.c:1.7 src/sys/arch/arm/sunxi/sun8i_h3_ccu.c:1.8 --- src/sys/arch/arm/sunxi/sun8i_h3_ccu.c:1.7 Fri Jul 7 21:19:50 2017 +++ src/sys/arch/arm/sunxi/sun8i_h3_ccu.c Mon Jul 17 23:26:17 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: sun8i_h3_ccu.c,v 1.7 2017/07/07 21:19:50 jmcneill Exp $ */ +/* $NetBSD: sun8i_h3_ccu.c,v 1.8 2017/07/17 23:26:17 jmcneill Exp $ */ /*- * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca> @@ -29,7 +29,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(1, "$NetBSD: sun8i_h3_ccu.c,v 1.7 2017/07/07 21:19:50 jmcneill Exp $"); +__KERNEL_RCSID(1, "$NetBSD: sun8i_h3_ccu.c,v 1.8 2017/07/17 23:26:17 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -184,12 +184,24 @@ static struct sunxi_ccu_clk sun8i_h3_ccu SUNXI_CCU_NM(H3_CLK_MMC0, "mmc0", mod_parents, SDMMC0_CLK_REG, __BITS(17, 16), __BITS(3,0), __BITS(25, 24), __BIT(31), SUNXI_CCU_NM_POWER_OF_TWO|SUNXI_CCU_NM_ROUND_DOWN), + SUNXI_CCU_PHASE(H3_CLK_MMC0_SAMPLE, "mmc0_sample", "mmc0", + SDMMC0_CLK_REG, __BITS(22,20)), + SUNXI_CCU_PHASE(H3_CLK_MMC0_OUTPUT, "mmc0_output", "mmc0", + SDMMC0_CLK_REG, __BITS(10,8)), SUNXI_CCU_NM(H3_CLK_MMC1, "mmc1", mod_parents, SDMMC1_CLK_REG, __BITS(17, 16), __BITS(3,0), __BITS(25, 24), __BIT(31), SUNXI_CCU_NM_POWER_OF_TWO|SUNXI_CCU_NM_ROUND_DOWN), + SUNXI_CCU_PHASE(H3_CLK_MMC1_SAMPLE, "mmc1_sample", "mmc1", + SDMMC1_CLK_REG, __BITS(22,20)), + SUNXI_CCU_PHASE(H3_CLK_MMC1_OUTPUT, "mmc1_output", "mmc1", + SDMMC1_CLK_REG, __BITS(10,8)), SUNXI_CCU_NM(H3_CLK_MMC2, "mmc2", mod_parents, SDMMC2_CLK_REG, __BITS(17, 16), __BITS(3,0), __BITS(25, 24), __BIT(31), SUNXI_CCU_NM_POWER_OF_TWO|SUNXI_CCU_NM_ROUND_DOWN), + SUNXI_CCU_PHASE(H3_CLK_MMC2_SAMPLE, "mmc2_sample", "mmc2", + SDMMC2_CLK_REG, __BITS(22,20)), + SUNXI_CCU_PHASE(H3_CLK_MMC2_OUTPUT, "mmc2_output", "mmc2", + SDMMC2_CLK_REG, __BITS(10,8)), SUNXI_CCU_GATE(H3_CLK_BUS_MMC0, "bus-mmc0", "ahb1", BUS_CLK_GATING_REG0, 8), Index: src/sys/arch/arm/sunxi/sunxi_ccu.c diff -u src/sys/arch/arm/sunxi/sunxi_ccu.c:1.5 src/sys/arch/arm/sunxi/sunxi_ccu.c:1.6 --- src/sys/arch/arm/sunxi/sunxi_ccu.c:1.5 Sun Jul 2 00:14:09 2017 +++ src/sys/arch/arm/sunxi/sunxi_ccu.c Mon Jul 17 23:26:17 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: sunxi_ccu.c,v 1.5 2017/07/02 00:14:09 jmcneill Exp $ */ +/* $NetBSD: sunxi_ccu.c,v 1.6 2017/07/17 23:26:17 jmcneill Exp $ */ /*- * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca> @@ -31,7 +31,7 @@ #include "opt_fdt_arm.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sunxi_ccu.c,v 1.5 2017/07/02 00:14:09 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sunxi_ccu.c,v 1.6 2017/07/17 23:26:17 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -329,6 +329,7 @@ sunxi_ccu_print(struct sunxi_ccu_softc * case SUNXI_CCU_NKMP: type = "nkmp"; break; case SUNXI_CCU_PREDIV: type = "prediv"; break; case SUNXI_CCU_DIV: type = "div"; break; + case SUNXI_CCU_PHASE: type = "phase"; break; default: type = "???"; break; } Index: src/sys/arch/arm/sunxi/sunxi_ccu.h diff -u src/sys/arch/arm/sunxi/sunxi_ccu.h:1.6 src/sys/arch/arm/sunxi/sunxi_ccu.h:1.7 --- src/sys/arch/arm/sunxi/sunxi_ccu.h:1.6 Thu Jul 6 22:10:14 2017 +++ src/sys/arch/arm/sunxi/sunxi_ccu.h Mon Jul 17 23:26:17 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: sunxi_ccu.h,v 1.6 2017/07/06 22:10:14 jmcneill Exp $ */ +/* $NetBSD: sunxi_ccu.h,v 1.7 2017/07/17 23:26:17 jmcneill Exp $ */ /*- * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca> @@ -61,6 +61,7 @@ enum sunxi_ccu_clktype { SUNXI_CCU_NKMP, SUNXI_CCU_PREDIV, SUNXI_CCU_DIV, + SUNXI_CCU_PHASE, }; struct sunxi_ccu_gate { @@ -252,6 +253,31 @@ const char *sunxi_ccu_prediv_get_parent( .get_parent = sunxi_ccu_prediv_get_parent, \ } +struct sunxi_ccu_phase { + bus_size_t reg; + const char *parent; + uint32_t mask; +}; + +u_int sunxi_ccu_phase_get_rate(struct sunxi_ccu_softc *, + struct sunxi_ccu_clk *); +int sunxi_ccu_phase_set_rate(struct sunxi_ccu_softc *, + struct sunxi_ccu_clk *, u_int); +const char *sunxi_ccu_phase_get_parent(struct sunxi_ccu_softc *, + struct sunxi_ccu_clk *); + +#define SUNXI_CCU_PHASE(_id, _name, _parent, _reg, _mask) \ + [_id] = { \ + .type = SUNXI_CCU_PHASE, \ + .base.name = (_name), \ + .u.phase.reg = (_reg), \ + .u.phase.parent = (_parent), \ + .u.phase.mask = (_mask), \ + .get_rate = sunxi_ccu_phase_get_rate, \ + .set_rate = sunxi_ccu_phase_set_rate, \ + .get_parent = sunxi_ccu_phase_get_parent, \ + } + struct sunxi_ccu_clk { struct clk base; enum sunxi_ccu_clktype type; @@ -261,6 +287,7 @@ struct sunxi_ccu_clk { struct sunxi_ccu_nkmp nkmp; struct sunxi_ccu_prediv prediv; struct sunxi_ccu_div div; + struct sunxi_ccu_phase phase; } u; int (*enable)(struct sunxi_ccu_softc *, Added files: Index: src/sys/arch/arm/sunxi/sunxi_ccu_phase.c diff -u /dev/null src/sys/arch/arm/sunxi/sunxi_ccu_phase.c:1.1 --- /dev/null Mon Jul 17 23:26:17 2017 +++ src/sys/arch/arm/sunxi/sunxi_ccu_phase.c Mon Jul 17 23:26:17 2017 @@ -0,0 +1,126 @@ +/* $NetBSD: sunxi_ccu_phase.c,v 1.1 2017/07/17 23:26:17 jmcneill Exp $ */ + +/*- + * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: sunxi_ccu_phase.c,v 1.1 2017/07/17 23:26:17 jmcneill Exp $"); + +#include <sys/param.h> +#include <sys/bus.h> + +#include <dev/clk/clk_backend.h> + +#include <arm/sunxi/sunxi_ccu.h> + +static u_int +sunxi_ccu_phase_get_parent_rate(struct clk *clkp) +{ + struct clk *clkp_parent; + + clkp_parent = clk_get_parent(clkp); + if (clkp_parent == NULL) + return 0; + + return clk_get_rate(clkp_parent); +} + +static u_int +sunxi_ccu_phase_div(u_int n, u_int d) +{ + return (n + (d/2)) / d; +} + +u_int +sunxi_ccu_phase_get_rate(struct sunxi_ccu_softc *sc, + struct sunxi_ccu_clk *clk) +{ + struct sunxi_ccu_phase *phase = &clk->u.phase; + struct clk *clkp = &clk->base; + u_int p_rate, gp_rate, p_div, delay; + uint32_t val; + + KASSERT(clk->type == SUNXI_CCU_PHASE); + + p_rate = sunxi_ccu_phase_get_parent_rate(clkp); + if (p_rate == 0) + return 0; + gp_rate = sunxi_ccu_phase_get_parent_rate(clk_get_parent(clkp)); + if (gp_rate == 0) + return 0; + + p_div = gp_rate / p_rate; + + val = CCU_READ(sc, phase->reg); + delay = __SHIFTOUT(val, phase->mask); + + return delay * sunxi_ccu_phase_div(360, p_div); +} + +int +sunxi_ccu_phase_set_rate(struct sunxi_ccu_softc *sc, + struct sunxi_ccu_clk *clk, u_int new_rate) +{ + struct sunxi_ccu_phase *phase = &clk->u.phase; + struct clk *clkp = &clk->base; + u_int p_rate, gp_rate, p_div, delay; + uint32_t val; + + KASSERT(clk->type == SUNXI_CCU_PHASE); + + clkp = &clk->base; + + p_rate = sunxi_ccu_phase_get_parent_rate(clkp); + if (p_rate == 0) + return 0; + gp_rate = sunxi_ccu_phase_get_parent_rate(clk_get_parent(clkp)); + if (gp_rate == 0) + return 0; + + p_div = gp_rate / p_rate; + + delay = new_rate == 180 ? 0 : + sunxi_ccu_phase_div(new_rate, + sunxi_ccu_phase_div(360, p_div)); + + val = CCU_READ(sc, phase->reg); + val &= ~phase->mask; + val |= __SHIFTIN(delay, phase->mask); + CCU_WRITE(sc, phase->reg, val); + + return 0; +} + +const char * +sunxi_ccu_phase_get_parent(struct sunxi_ccu_softc *sc, + struct sunxi_ccu_clk *clk) +{ + struct sunxi_ccu_phase *phase = &clk->u.phase; + + KASSERT(clk->type == SUNXI_CCU_PHASE); + + return phase->parent; +}