Module Name: src Committed By: hkenken Date: Tue Nov 12 04:32:36 UTC 2019
Modified Files: src/sys/arch/arm/imx: imx6_ccm.c Log Message: Add imxccm_clk_set_rate_div(). + Fixed BUG in imxccm_clk_get_rate_div(). To generate a diff of this commit: cvs rdiff -u -r1.14 -r1.15 src/sys/arch/arm/imx/imx6_ccm.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/imx/imx6_ccm.c diff -u src/sys/arch/arm/imx/imx6_ccm.c:1.14 src/sys/arch/arm/imx/imx6_ccm.c:1.15 --- src/sys/arch/arm/imx/imx6_ccm.c:1.14 Mon Sep 2 01:28:41 2019 +++ src/sys/arch/arm/imx/imx6_ccm.c Tue Nov 12 04:32:36 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: imx6_ccm.c,v 1.14 2019/09/02 01:28:41 hkenken Exp $ */ +/* $NetBSD: imx6_ccm.c,v 1.15 2019/11/12 04:32:36 hkenken Exp $ */ /* * Copyright (c) 2010-2012, 2014 Genetec Corporation. All rights reserved. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: imx6_ccm.c,v 1.14 2019/09/02 01:28:41 hkenken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: imx6_ccm.c,v 1.15 2019/11/12 04:32:36 hkenken Exp $"); #include "opt_cputypes.h" @@ -1165,7 +1165,7 @@ imxccm_clk_get_rate_div(struct imxccm_so KASSERT(div->tbl != NULL); for (int i = 0; div->tbl[i] != 0; i++) - if (div->tbl[i] == n) + if (i == n) rate /= div->tbl[i]; } else { rate /= n + 1; @@ -1275,13 +1275,56 @@ imxccm_clk_get_parent_mux(struct imxccm_ static int imxccm_clk_set_rate_pll(struct imxccm_softc *sc, - struct imx6_clk *eclk, u_int rate) + struct imx6_clk *iclk, u_int rate) { /* ToDo */ return EOPNOTSUPP; } +static int +imxccm_clk_set_rate_div(struct imxccm_softc *sc, + struct imx6_clk *iclk, u_int rate) +{ + struct imx6_clk_div *div = &iclk->clk.div; + struct imx6_clk *parent; + + KASSERT(iclk->type == IMX6_CLK_DIV); + + parent = imx6_clk_find(iclk->parent); + KASSERT(parent != NULL); + + u_int rate_parent = imxccm_clk_get_rate(sc, &parent->base); + u_int divider = rate_parent / rate; + + KASSERT(div->tbl != NULL); + + bus_space_handle_t ioh; + if (div->base == IMX6_CLK_REG_CCM_ANALOG) + ioh = sc->sc_ioh_analog; + else + ioh = sc->sc_ioh; + + uint32_t v = bus_space_read_4(sc->sc_iot, ioh, div->reg); + v &= ~div->mask; + if (div->type == IMX6_CLK_DIV_TABLE) { + int n = -1; + for (int i = 0; div->tbl[i] != 0; i++) + if (div->tbl[i] == divider) + n = i; + + if (n >= 0) + v |= __SHIFTIN(n, div->mask); + else + return EINVAL; + } else { + v |= __SHIFTIN(divider - 1, div->mask); + } + bus_space_write_4(sc->sc_iot, ioh, div->reg, v); + + return 0; +} + /* * CLK Driver APIs */ @@ -1345,13 +1388,15 @@ imxccm_clk_set_rate(void *priv, struct c switch (iclk->type) { case IMX6_CLK_FIXED: case IMX6_CLK_FIXED_FACTOR: - return EIO; + return ENXIO; case IMX6_CLK_PLL: return imxccm_clk_set_rate_pll(sc, iclk, rate); case IMX6_CLK_MUX: - return EIO; + return ENXIO; case IMX6_CLK_GATE: + return ENXIO; case IMX6_CLK_DIV: + return imxccm_clk_set_rate_div(sc, iclk, rate); case IMX6_CLK_PFD: return EINVAL; default: