svn commit: r310178 - head/sys/arm/allwinner/clk
Emmanuel Vadot
manu at FreeBSD.org
Fri Dec 16 21:58:51 UTC 2016
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;
More information about the svn-src-all
mailing list