Index: sys/arm/allwinner/clkng/aw_clk.h =================================================================== --- sys/arm/allwinner/clkng/aw_clk.h +++ sys/arm/allwinner/clkng/aw_clk.h @@ -48,6 +48,7 @@ Clock Source/Divider N/Divider M Clock Source/Divider N/Divider M/2 +Clock Source*N/(Divider M+1)/(Divider P+1) */ @@ -70,6 +71,8 @@ #define AW_CLK_FACTOR_ZERO_BASED 0x0002 #define AW_CLK_FACTOR_HAS_COND 0x0004 #define AW_CLK_FACTOR_FIXED 0x0008 +#define AW_CLK_FACTOR_POWER_OF_FOUR 0x0010 +#define AW_CLK_FACTOR_HAS_BIT_COND 0x0020 struct aw_clk_factor { uint32_t shift; /* Shift bits for the factor */ @@ -98,9 +101,14 @@ uint32_t factor_val; uint32_t cond; - if (factor->flags & AW_CLK_FACTOR_HAS_COND) { + if ((factor->flags & AW_CLK_FACTOR_HAS_COND) || + (factor->flags & AW_CLK_FACTOR_HAS_BIT_COND)) { cond = (val & factor->cond_mask) >> factor->cond_shift; - if (cond != factor->cond_value) + if (!(factor->flags & AW_CLK_FACTOR_HAS_BIT_COND) && + cond != factor->cond_value) + return (1); + if ((factor->flags & AW_CLK_FACTOR_HAS_BIT_COND) && + (cond & factor->cond_value) == 0) return (1); } @@ -112,10 +120,24 @@ factor_val += 1; else if (factor->flags & AW_CLK_FACTOR_POWER_OF_TWO) factor_val = 1 << factor_val; + else if (factor->flags & AW_CLK_FACTOR_POWER_OF_FOUR) + factor_val = 1 << (2 * factor_val); return (factor_val); } +static inline uint32_t +aw_clk_factor_get_incremented(uint32_t val, struct aw_clk_factor *factor) +{ + + if (factor->flags & AW_CLK_FACTOR_POWER_OF_TWO) + return (val << 1); + else if (factor->flags & AW_CLK_FACTOR_POWER_OF_FOUR) + return (val << 2); + else + return (val + 1); +} + static inline uint32_t aw_clk_factor_get_max(struct aw_clk_factor *factor) { @@ -125,6 +147,8 @@ max = factor->value; else if (factor->flags & AW_CLK_FACTOR_POWER_OF_TWO) max = 1 << ((1 << factor->width) - 1); + else if (factor->flags & AW_CLK_FACTOR_POWER_OF_FOUR) + max = 1 << (2 * ((1 << factor->width) - 1)); else { max = (1 << factor->width); } @@ -160,6 +184,9 @@ else if (factor->flags & AW_CLK_FACTOR_POWER_OF_TWO) { for (val = 0; raw != 1; val++) raw >>= 1; + } else if (factor->flags & AW_CLK_FACTOR_POWER_OF_FOUR) { + for (val = 0; raw != 1; val++) + raw >>= 2; } else val = raw - 1; Index: sys/arm/allwinner/clkng/aw_clk_nkmp.c =================================================================== --- sys/arm/allwinner/clkng/aw_clk_nkmp.c +++ sys/arm/allwinner/clkng/aw_clk_nkmp.c @@ -168,25 +168,13 @@ } if (best == *fout) return (best); - if ((sc->p.flags & AW_CLK_FACTOR_POWER_OF_TWO) != 0) - p <<= 1; - else - p++; + p = aw_clk_factor_get_incremented(p, &sc->p); } - if ((sc->m.flags & AW_CLK_FACTOR_POWER_OF_TWO) != 0) - m <<= 1; - else - m++; + m = aw_clk_factor_get_incremented(m, &sc->m); } - if ((sc->k.flags & AW_CLK_FACTOR_POWER_OF_TWO) != 0) - k <<= 1; - else - k++; + k = aw_clk_factor_get_incremented(k, &sc->k); } - if ((sc->n.flags & AW_CLK_FACTOR_POWER_OF_TWO) != 0) - n <<= 1; - else - n++; + n = aw_clk_factor_get_incremented(n, &sc->n); } return best; Index: sys/arm/allwinner/clkng/aw_clk_nm.c =================================================================== --- sys/arm/allwinner/clkng/aw_clk_nm.c +++ sys/arm/allwinner/clkng/aw_clk_nm.c @@ -160,15 +160,9 @@ *factor_m = m; } - if ((sc->n.flags & AW_CLK_FACTOR_POWER_OF_TWO) != 0) - n <<= 1; - else - n++; + n = aw_clk_factor_get_incremented(n, &sc->n); } - if ((sc->m.flags & AW_CLK_FACTOR_POWER_OF_TWO) != 0) - m <<= 1; - else - m++; + m = aw_clk_factor_get_incremented(m, &sc->m); } return (best);