Author: manu
Date: Fri Dec 16 21:58:48 2016
New Revision: 310178
URL: https://svnweb.freebsd.org/changeset/base/310178

Log:
  Honor the CLK_SET_DRYRUN for the *set_freq function for allwinner clocks.
  
  Reviewed by:  jmcneill
  MFC after:    1 month
  Differential Revision:        https://reviews.freebsd.org/D8821

Modified:
  head/sys/arm/allwinner/clk/aw_debeclk.c
  head/sys/arm/allwinner/clk/aw_hdmiclk.c
  head/sys/arm/allwinner/clk/aw_lcdclk.c
  head/sys/arm/allwinner/clk/aw_mmcclk.c
  head/sys/arm/allwinner/clk/aw_modclk.c
  head/sys/arm/allwinner/clk/aw_pll.c
  head/sys/arm/allwinner/clk/aw_thsclk.c

Modified: head/sys/arm/allwinner/clk/aw_debeclk.c
==============================================================================
--- head/sys/arm/allwinner/clk/aw_debeclk.c     Fri Dec 16 21:10:37 2016        
(r310177)
+++ head/sys/arm/allwinner/clk/aw_debeclk.c     Fri Dec 16 21:58:48 2016        
(r310178)
@@ -209,6 +209,12 @@ aw_debeclk_set_freq(struct clknode *clk,
 
        m = howmany(fin, *fout) - 1;
 
+       *fout = fin / (m + 1);
+       *stop = 1;
+
+       if ((flags & CLK_SET_DRYRUN) != 0)
+               return (0);
+
        DEVICE_LOCK(sc);
        DEBECLK_READ(sc, &val);
        val &= ~CLK_RATIO_M;
@@ -216,9 +222,6 @@ aw_debeclk_set_freq(struct clknode *clk,
        DEBECLK_WRITE(sc, val);
        DEVICE_UNLOCK(sc);
 
-       *fout = fin / (m + 1);
-       *stop = 1;
-
        return (0);
 }
 

Modified: head/sys/arm/allwinner/clk/aw_hdmiclk.c
==============================================================================
--- head/sys/arm/allwinner/clk/aw_hdmiclk.c     Fri Dec 16 21:10:37 2016        
(r310177)
+++ head/sys/arm/allwinner/clk/aw_hdmiclk.c     Fri Dec 16 21:58:48 2016        
(r310178)
@@ -188,6 +188,12 @@ aw_hdmiclk_set_freq(struct clknode *clk,
        if (best_diff == (int64_t)*fout)
                return (ERANGE);
 
+       *fout = fin / (1 << best_n) / (best_m + 1);
+       *stop = 1;
+
+       if ((flags & CLK_SET_DRYRUN) != 0)
+               return (0);
+
        DEVICE_LOCK(sc);
        HDMICLK_READ(sc, &val);
        val &= ~(CLK_RATIO_N | CLK_RATIO_M);
@@ -196,9 +202,6 @@ aw_hdmiclk_set_freq(struct clknode *clk,
        HDMICLK_WRITE(sc, val);
        DEVICE_UNLOCK(sc);
 
-       *fout = fin / (1 << best_n) / (best_m + 1);
-       *stop = 1;
-
        return (0);
 }
 

Modified: head/sys/arm/allwinner/clk/aw_lcdclk.c
==============================================================================
--- head/sys/arm/allwinner/clk/aw_lcdclk.c      Fri Dec 16 21:10:37 2016        
(r310177)
+++ head/sys/arm/allwinner/clk/aw_lcdclk.c      Fri Dec 16 21:58:48 2016        
(r310178)
@@ -389,56 +389,69 @@ aw_lcdclk_set_freq(struct clknode *clk, 
     int flags, int *stop)
 {
        struct aw_lcdclk_softc *sc;
+       struct clknode *parent_clk;
+       const char **parent_names;
        uint64_t pll_freq;
        uint32_t val, src_sel;
        int error, tcon_pll_div;
 
        sc = clknode_get_softc(clk);
 
-       switch (sc->type) {
-       case AW_LCD_CH0:
+       if (sc->type == AW_LCD_CH0) {
                *stop = 0;
-               break;
-       case AW_LCD_CH1:
-               if (sc->id != CLK_IDX_CH1_SCLK2)
-                       return (ENXIO);
+               return (0);
+       }
 
-               src_sel = calc_tcon_pll(fin, *fout, &pll_freq, &tcon_pll_div);
+       if (sc->id != CLK_IDX_CH1_SCLK2)
+               return (ENXIO);
 
-               /* Switch parent clock if necessary */
-               if (src_sel != clknode_get_parent_idx(clk)) {
-                       error = clknode_set_parent_by_idx(clk, src_sel);
-                       if (error != 0)
-                               return (error);
-               }
+       src_sel = calc_tcon_pll(fin, *fout, &pll_freq, &tcon_pll_div);
 
-               error = clknode_set_freq(clknode_get_parent(clk), pll_freq,
-                   0, 0);
-               if (error != 0)
-                       return (error);
-
-               error = clknode_enable(clknode_get_parent(clk));
-               if (error != 0)
-                       return (error);
-
-               /* Fetch new input frequency */
-               error = clknode_get_freq(clknode_get_parent(clk), &pll_freq);
-               if (error != 0)
-                       return (error);
-
-               /* Set LCD divisor */
-               DEVICE_LOCK(sc);
-               LCDCLK_READ(sc, &val);
-               val &= ~CH1_CLK_DIV_RATIO_M;
-               val |= ((tcon_pll_div - 1) << CH1_CLK_DIV_RATIO_M_SHIFT);
-               LCDCLK_WRITE(sc, val);
-               DEVICE_UNLOCK(sc);
+       parent_names = clknode_get_parent_names(clk);
+       parent_clk = clknode_find_by_name(parent_names[src_sel]);
 
-               *fout = pll_freq / tcon_pll_div;
-               *stop = 1;
+       if (parent_clk == NULL)
+               return (ERANGE);
 
-               break;
-       }
+       /* Fetch input frequency */
+       error = clknode_get_freq(parent_clk, &pll_freq);
+       if (error != 0)
+               return (error);
+
+       *fout = pll_freq / tcon_pll_div;
+       *stop = 1;
+
+       if ((flags & CLK_SET_DRYRUN) != 0)
+               return (0);
+
+       /* Switch parent clock if necessary */
+       error = clknode_set_parent_by_idx(clk, src_sel);
+       if (error != 0)
+               return (error);
+
+       error = clknode_set_freq(parent_clk, pll_freq,
+           0, 0);
+       if (error != 0)
+               return (error);
+
+       /* Fetch new input frequency */
+       error = clknode_get_freq(parent_clk, &pll_freq);
+       if (error != 0)
+               return (error);
+
+       *fout = pll_freq / tcon_pll_div;
+
+       error = clknode_enable(parent_clk);
+       if (error != 0)
+               return (error);
+
+       /* Set LCD divisor */
+       DEVICE_LOCK(sc);
+       LCDCLK_READ(sc, &val);
+       val &= ~CH1_CLK_DIV_RATIO_M;
+       val |= ((tcon_pll_div - 1) << CH1_CLK_DIV_RATIO_M_SHIFT);
+       LCDCLK_WRITE(sc, val);
+       DEVICE_UNLOCK(sc);
 
        return (0);
 }

Modified: head/sys/arm/allwinner/clk/aw_mmcclk.c
==============================================================================
--- head/sys/arm/allwinner/clk/aw_mmcclk.c      Fri Dec 16 21:10:37 2016        
(r310177)
+++ head/sys/arm/allwinner/clk/aw_mmcclk.c      Fri Dec 16 21:58:48 2016        
(r310178)
@@ -77,6 +77,20 @@ struct aw_mmcclk_sc {
        bus_addr_t      reg;
 };
 
+struct phase_clk {
+       uint64_t        freq;
+       int             parent_idx;
+       uint32_t        ophase;
+       uint32_t        phase;
+       uint32_t        n;
+};
+
+static struct phase_clk aw_mmcclk_phase[] = {
+       {400000, CLK_SRC_SEL_OSC24M, 0, 0, 2},
+       {25000000, CLK_SRC_SEL_PLL6, 0, 5, 2},
+       {52000000, CLK_SRC_SEL_PLL6, 3, 5, 0},
+};
+
 #define        MODCLK_READ(sc, val)    CLKDEV_READ_4((sc)->clkdev, (sc)->reg, 
(val))
 #define        MODCLK_WRITE(sc, val)   CLKDEV_WRITE_4((sc)->clkdev, (sc)->reg, 
(val))
 #define        DEVICE_LOCK(sc)         CLKDEV_DEVICE_LOCK((sc)->clkdev)
@@ -166,8 +180,10 @@ aw_mmcclk_set_freq(struct clknode *clk, 
     int flags, int *stop)
 {
        struct aw_mmcclk_sc *sc;
-       uint32_t val, m, n, phase, ophase;
-       int parent_idx, error;
+       struct clknode *parent_clk;
+       const char **parent_names;
+       uint32_t val, m;
+       int parent_idx, error, phase;
 
        sc = clknode_get_softc(clk);
 
@@ -175,52 +191,49 @@ aw_mmcclk_set_freq(struct clknode *clk, 
         * The ophase/phase values should be set by the MMC driver, but
         * there is currently no way to do this with the clk API
         */
-       if (*fout <= 400000) {
-               parent_idx = CLK_SRC_SEL_OSC24M;
-               ophase = 0;
-               phase = 0;
-               n = 2;
-       } else if (*fout <= 25000000) {
-               parent_idx = CLK_SRC_SEL_PLL6;
-               ophase = 0;
-               phase = 5;
-               n = 2;
-       } else if (*fout <= 52000000) {
-               parent_idx = CLK_SRC_SEL_PLL6;
-               ophase = 3;
-               phase = 5;
-               n = 0;
-       } else
+       for (phase = 0; phase < nitems(aw_mmcclk_phase); phase++) {
+               if (*fout <= aw_mmcclk_phase[phase].freq)
+                       break;
+       }
+
+       if (phase == nitems(aw_mmcclk_phase))
                return (ERANGE);
 
-       /* Switch parent clock, if necessary */
-       if (parent_idx != clknode_get_parent_idx(clk)) {
-               error = clknode_set_parent_by_idx(clk, parent_idx);
-               if (error != 0)
-                       return (error);
-
-               /* Fetch new input frequency */
-               error = clknode_get_freq(clknode_get_parent(clk), &fin);
-               if (error != 0)
-                       return (error);
-       }
+       parent_names = clknode_get_parent_names(clk);
+       parent_idx = aw_mmcclk_phase[phase].parent_idx;
+       parent_clk = clknode_find_by_name(parent_names[parent_idx]);
+
+       if (parent_clk == NULL)
+               return (ERANGE);
+
+       error = clknode_get_freq(parent_clk, &fin);
+       if (error != 0)
+               return (error);
+
+       m = ((fin / (1 << aw_mmcclk_phase[phase].n)) / *fout) - 1;
+
+       *fout = fin / (1 << aw_mmcclk_phase[phase].n) / (m + 1);
+       *stop = 1;
+
+       if ((flags & CLK_SET_DRYRUN) != 0)
+               return (0);
 
-       m = ((fin / (1 << n)) / *fout) - 1;
+       /* Switch to the correct parent if needed */
+       error = clknode_set_parent_by_idx(clk, parent_idx);
+       if (error != 0)
+               return (error);
 
        DEVICE_LOCK(sc);
        MODCLK_READ(sc, &val);
        val &= ~(CLK_RATIO_N | CLK_RATIO_M | CLK_PHASE_CTR |
            OUTPUT_CLK_PHASE_CTR);
-       val |= (n << CLK_RATIO_N_SHIFT);
+       val |= (aw_mmcclk_phase[phase].n << CLK_RATIO_N_SHIFT);
        val |= (m << CLK_RATIO_M_SHIFT);
-       val |= (phase << CLK_PHASE_CTR_SHIFT);
-       val |= (ophase << OUTPUT_CLK_PHASE_CTR_SHIFT);
+       val |= (aw_mmcclk_phase[phase].phase << CLK_PHASE_CTR_SHIFT);
+       val |= (aw_mmcclk_phase[phase].ophase << OUTPUT_CLK_PHASE_CTR_SHIFT);
        MODCLK_WRITE(sc, val);
        DEVICE_UNLOCK(sc);
 
-       *fout = fin / (1 << n) / (m + 1);
-       *stop = 1;
-
        return (0);
 }
 

Modified: head/sys/arm/allwinner/clk/aw_modclk.c
==============================================================================
--- head/sys/arm/allwinner/clk/aw_modclk.c      Fri Dec 16 21:10:37 2016        
(r310177)
+++ head/sys/arm/allwinner/clk/aw_modclk.c      Fri Dec 16 21:58:48 2016        
(r310178)
@@ -68,7 +68,6 @@ static struct ofw_compat_data compat_dat
 struct aw_modclk_sc {
        device_t        clkdev;
        bus_addr_t      reg;
-       u_int           parent_cnt;
 };
 
 #define        MODCLK_READ(sc, val)    CLKDEV_READ_4((sc)->clkdev, (sc)->reg, 
(val))
@@ -102,7 +101,7 @@ aw_modclk_set_mux(struct clknode *clk, i
 
        sc = clknode_get_softc(clk);
 
-       if (index < 0 || index >= sc->parent_cnt)
+       if (index < 0 || index >= clknode_get_parents_num(clk))
                return (ERANGE);
 
        DEVICE_LOCK(sc);
@@ -160,6 +159,8 @@ aw_modclk_set_freq(struct clknode *clk, 
     int flags, int *stop)
 {
        struct aw_modclk_sc *sc;
+       struct clknode *parent_clk, *best_parent;
+       const char **parent_names;
        uint32_t val, m, n, src, best_m, best_n, best_src;
        uint64_t cur_freq;
        int64_t best_diff, cur_diff;
@@ -170,11 +171,12 @@ aw_modclk_set_freq(struct clknode *clk, 
        best_diff = (int64_t)*fout; 
        best_src = 0;
 
-       for (src = 0; src < sc->parent_cnt; src++) {
-               error = clknode_set_parent_by_idx(clk, src);
-               if (error != 0)
+       parent_names = clknode_get_parent_names(clk);
+       for (src = 0; src < clknode_get_parents_num(clk); src++) {
+               parent_clk = clknode_find_by_name(parent_names[src]);
+               if (parent_clk == NULL)
                        continue;
-               error = clknode_get_freq(clknode_get_parent(clk), &fin);
+               error = clknode_get_freq(parent_clk, &fin);
                if (error != 0)
                        continue;
 
@@ -184,6 +186,7 @@ aw_modclk_set_freq(struct clknode *clk, 
                                cur_diff = (int64_t)*fout - cur_freq;
                                if (cur_diff >= 0 && cur_diff < best_diff) {
                                        best_src = src;
+                                       best_parent = parent_clk;
                                        best_diff = cur_diff;
                                        best_m = m;
                                        best_n = n;
@@ -194,10 +197,17 @@ aw_modclk_set_freq(struct clknode *clk, 
        if (best_diff == (int64_t)*fout)
                return (ERANGE);
 
-       error = clknode_set_parent_by_idx(clk, best_src);
+       error = clknode_get_freq(best_parent, &fin);
        if (error != 0)
                return (error);
-       error = clknode_get_freq(clknode_get_parent(clk), &fin);
+
+       *fout = fin / (1 << best_n) / (best_m + 1);
+       *stop = 1;
+
+       if ((flags & CLK_SET_DRYRUN) != 0)
+               return (0);
+
+       error = clknode_set_parent_by_idx(clk, best_src);
        if (error != 0)
                return (error);
 
@@ -209,9 +219,6 @@ aw_modclk_set_freq(struct clknode *clk, 
        MODCLK_WRITE(sc, val);
        DEVICE_UNLOCK(sc);
 
-       *fout = fin / (1 << best_n) / (best_m + 1);
-       *stop = 1;
-
        return (0);
 }
 
@@ -299,7 +306,6 @@ aw_modclk_attach(device_t dev)
        sc = clknode_get_softc(clk);
        sc->reg = paddr;
        sc->clkdev = device_get_parent(dev);
-       sc->parent_cnt = def.parent_cnt;
 
        clknode_register(clkdom, clk);
 

Modified: head/sys/arm/allwinner/clk/aw_pll.c
==============================================================================
--- head/sys/arm/allwinner/clk/aw_pll.c Fri Dec 16 21:10:37 2016        
(r310177)
+++ head/sys/arm/allwinner/clk/aw_pll.c Fri Dec 16 21:58:48 2016        
(r310178)
@@ -342,6 +342,9 @@ a10_pll1_set_freq(struct aw_pll_sc *sc, 
        if (f == NULL)
                return (EINVAL);
 
+       if ((flags & CLK_SET_DRYRUN) != 0)
+               return (0);
+
        DEVICE_LOCK(sc);
        PLL_READ(sc, &val);
        val &= ~(A10_PLL1_FACTOR_N|A10_PLL1_FACTOR_K|A10_PLL1_FACTOR_M|
@@ -440,6 +443,9 @@ a10_pll2_set_freq(struct aw_pll_sc *sc, 
        post_div = 4;
        n = (*fout * pre_div * post_div * 2) / (2 * fin);
 
+       if ((flags & CLK_SET_DRYRUN) != 0)
+               return (0);
+
        DEVICE_LOCK(sc);
        PLL_READ(sc, &val);
        val &= ~(A10_PLL2_POST_DIV | A10_PLL2_FACTOR_N | A10_PLL2_PRE_DIV);
@@ -497,6 +503,9 @@ a10_pll3_set_freq(struct aw_pll_sc *sc, 
                *fout = m * A10_PLL3_REF_FREQ;
        }
 
+       if ((flags & CLK_SET_DRYRUN) != 0)
+               return (0);
+
        DEVICE_LOCK(sc);
        PLL_READ(sc, &val);
        val &= ~(A10_PLL3_MODE_SEL | A10_PLL3_FUNC_SET | A10_PLL3_FACTOR_M);
@@ -699,6 +708,9 @@ a13_pll2_set_freq(struct aw_pll_sc *sc, 
        post_div = 4;
        n = (*fout * pre_div * post_div * 2) / (2 * fin);
 
+       if ((flags & CLK_SET_DRYRUN) != 0)
+               return (0);
+
        DEVICE_LOCK(sc);
        PLL_READ(sc, &val);
        val &= ~(A13_PLL2_POST_DIV | A13_PLL2_FACTOR_N | A13_PLL2_PRE_DIV);
@@ -765,6 +777,9 @@ h3_pll2_set_freq(struct aw_pll_sc *sc, u
        if (f == NULL)
                return (EINVAL);
 
+       if ((flags & CLK_SET_DRYRUN) != 0)
+               return (0);
+
        DEVICE_LOCK(sc);
        PLL_READ(sc, &val);
        val &= ~(H3_PLL2_POST_DIV|H3_PLL2_FACTOR_N|H3_PLL2_PRE_DIV);
@@ -808,6 +823,9 @@ a23_pll1_set_freq(struct aw_pll_sc *sc, 
        if (f == NULL)
                return (EINVAL);
 
+       if ((flags & CLK_SET_DRYRUN) != 0)
+               return (0);
+
        DEVICE_LOCK(sc);
        PLL_READ(sc, &val);
        val &= ~(A23_PLL1_FACTOR_N|A23_PLL1_FACTOR_K|A23_PLL1_FACTOR_M|
@@ -860,6 +878,9 @@ h3_pll1_set_freq(struct aw_pll_sc *sc, u
        if (f == NULL)
                return (EINVAL);
 
+       if ((flags & CLK_SET_DRYRUN) != 0)
+               return (0);
+
        DEVICE_LOCK(sc);
        PLL_READ(sc, &val);
 
@@ -1067,6 +1088,9 @@ a83t_pllcpux_set_freq(struct aw_pll_sc *
        if (n < A83T_PLLCPUX_FACTOR_N_MIN || n > A83T_PLLCPUX_FACTOR_N_MAX)
                return (EINVAL);
 
+       if ((flags & CLK_SET_DRYRUN) != 0)
+               return (0);
+
        DEVICE_LOCK(sc);
        PLL_READ(sc, &val);
        val &= ~A83T_PLLCPUX_FACTOR_N;

Modified: head/sys/arm/allwinner/clk/aw_thsclk.c
==============================================================================
--- head/sys/arm/allwinner/clk/aw_thsclk.c      Fri Dec 16 21:10:37 2016        
(r310177)
+++ head/sys/arm/allwinner/clk/aw_thsclk.c      Fri Dec 16 21:58:48 2016        
(r310178)
@@ -186,6 +186,9 @@ aw_thsclk_set_freq(struct clknode *clk, 
        if (best_diff == (int64_t)*fout || best_n == 0)
                return (ERANGE);
 
+       if ((flags & CLK_SET_DRYRUN) != 0)
+               return (0);
+
        DEVICE_LOCK(sc);
        THSCLK_READ(sc, &val);
        val &= ~CLK_DIV_RATIO;
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to