From 9370bb92b2d16684ee45cf24e879c93c509162da Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Thu, 19 Dec 2024 01:47:39 +0000 Subject: [PATCH] add wifi6 8852be driver --- kernel/drivers/clk/rockchip/clk-pll.c | 173 ++++++++++++++++++++++++++++++++++++++++++++++----------- 1 files changed, 139 insertions(+), 34 deletions(-) diff --git a/kernel/drivers/clk/rockchip/clk-pll.c b/kernel/drivers/clk/rockchip/clk-pll.c index 91a0674..89ecdd0 100644 --- a/kernel/drivers/clk/rockchip/clk-pll.c +++ b/kernel/drivers/clk/rockchip/clk-pll.c @@ -332,6 +332,64 @@ return rate_table; } +static u32 +rockchip_rk3588_pll_frac_get(u32 m, u32 p, u32 s, u64 fin_hz, u64 fvco) +{ + u64 fref, fout, ffrac; + u32 k = 0; + + fref = fin_hz / p; + ffrac = fvco - (m * fref); + fout = ffrac * 65536; + k = fout / fref; + if (k > 32767) { + fref = fin_hz / p; + ffrac = ((m + 1) * fref) - fvco; + fout = ffrac * 65536; + k = ((fout * 10 / fref) + 7) / 10; + if (k > 32767) + k = 0; + else + k = ~k + 1; + } + return k; +} + +static struct rockchip_pll_rate_table * +rockchip_rk3588_pll_frac_by_auto(unsigned long fin_hz, unsigned long fout_hz) +{ + struct rockchip_pll_rate_table *rate_table = rk_pll_rate_table_get(); + u64 fvco_min = 2250 * MHZ, fvco_max = 4500 * MHZ; + u32 p, m, s, k; + u64 fvco; + + for (s = 0; s <= 6; s++) { + fvco = (u64)fout_hz << s; + if (fvco < fvco_min || fvco > fvco_max) + continue; + for (p = 1; p <= 4; p++) { + for (m = 64; m <= 1023; m++) { + if ((fvco >= m * fin_hz / p) && (fvco < (m + 1) * fin_hz / p)) { + k = rockchip_rk3588_pll_frac_get(m, p, s, + (u64)fin_hz, + fvco); + if (!k) + continue; + rate_table->p = p; + rate_table->s = s; + rate_table->k = k; + if (k > 32767) + rate_table->m = m + 1; + else + rate_table->m = m; + return rate_table; + } + } + } + } + return NULL; +} + static struct rockchip_pll_rate_table * rockchip_rk3588_pll_clk_set_by_auto(struct rockchip_clk_pll *pll, unsigned long fin_hz, @@ -341,7 +399,7 @@ u64 fvco_min = 2250 * MHZ, fvco_max = 4500 * MHZ; u64 fout_min = 37 * MHZ, fout_max = 4500 * MHZ; u32 p, m, s; - u64 fvco, fref, fout, ffrac; + u64 fvco; if (fin_hz == 0 || fout_hz == 0 || fout_hz == fin_hz) return NULL; @@ -368,26 +426,11 @@ } pr_err("CANNOT FIND Fout by auto,fout = %lu\n", fout_hz); } else { - for (s = 0; s <= 6; s++) { - fvco = (u64)fout_hz << s; - if (fvco < fvco_min || fvco > fvco_max) - continue; - for (p = 1; p <= 4; p++) { - for (m = 64; m <= 1023; m++) { - if ((fvco >= m * fin_hz / p) && (fvco < (m + 1) * fin_hz / p)) { - rate_table->p = p; - rate_table->m = m; - rate_table->s = s; - fref = fin_hz / p; - ffrac = fvco - (m * fref); - fout = ffrac * 65536; - rate_table->k = fout / fref; - return rate_table; - } - } - } - } - pr_err("CANNOT FIND Fout by auto,fout = %lu\n", fout_hz); + rate_table = rockchip_rk3588_pll_frac_by_auto(fin_hz, fout_hz); + if (!rate_table) + pr_err("CANNOT FIND Fout by auto,fout = %lu\n", fout_hz); + else + return rate_table; } return NULL; } @@ -1345,7 +1388,17 @@ rate64 *= cur.m; do_div(rate64, cur.p); - if (cur.k) { + if (cur.k & BIT(15)) { + /* fractional mode */ + u64 frac_rate64; + + cur.k = (~(cur.k - 1)) & RK3588_PLLCON2_K_MASK; + frac_rate64 = prate * cur.k; + postdiv = cur.p; + postdiv *= 65536; + do_div(frac_rate64, postdiv); + rate64 -= frac_rate64; + } else { /* fractional mode */ u64 frac_rate64 = prate * cur.k; @@ -1516,7 +1569,7 @@ { struct clk *parent = clk_get_parent(clk); struct rockchip_clk_pll *pll; - static u32 frac, fbdiv; + static u32 frac, fbdiv, s, p; bool negative; u32 pllcon, pllcon0, pllcon2, fbdiv_mask, frac_mask, frac_shift; u64 fracdiv, m, n; @@ -1567,11 +1620,6 @@ negative = !!(ppm & BIT(31)); ppm = negative ? ~ppm + 1 : ppm; - if (!frac) { - frac = readl_relaxed(pll->reg_base + pllcon2) & frac_mask; - fbdiv = readl_relaxed(pll->reg_base + pllcon0) & fbdiv_mask; - } - switch (pll->type) { case pll_rk3036: case pll_rk3328: @@ -1583,6 +1631,10 @@ * 1 << 24 1 << 24 1000000 * */ + if (!frac) { + frac = readl_relaxed(pll->reg_base + pllcon2) & frac_mask; + fbdiv = readl_relaxed(pll->reg_base + pllcon0) & fbdiv_mask; + } m = div64_u64((uint64_t)frac * ppm, 1000000); n = div64_u64((uint64_t)ppm << 24, 1000000) * fbdiv; @@ -1597,13 +1649,65 @@ writel_relaxed(pllcon, pll->reg_base + pllcon2); break; case pll_rk3588: - m = div64_u64((uint64_t)frac * ppm, 100000); - n = div64_u64((uint64_t)ppm * 65535 * fbdiv, 100000); + if (!fbdiv) { + frac = readl_relaxed(pll->reg_base + pllcon2) & frac_mask; + fbdiv = readl_relaxed(pll->reg_base + pllcon0) & fbdiv_mask; + } + if (!frac) { + pllcon = readl_relaxed(pll->reg_base + RK3588_PLLCON(1)); + s = ((pllcon >> RK3588_PLLCON1_S_SHIFT) + & RK3588_PLLCON1_S_MASK); + p = ((pllcon >> RK3588_PLLCON1_P_SHIFT) + & RK3588_PLLCON1_P_MASK); + m = div64_u64((uint64_t)clk_get_rate(clk) * ppm, 24000000); + n = div64_u64((uint64_t)m * 65536 * p * (1 << s), 1000000); - fracdiv = negative ? frac - (div64_u64(m + n, 10)) : frac + (div64_u64(m + n, 10)); - - if (!frac || fracdiv > frac_mask) - return -EINVAL; + if (n > 32767) + return -EINVAL; + fracdiv = negative ? ~n + 1 : n; + } else if (frac & BIT(15)) { + frac = (~(frac - 1)) & RK3588_PLLCON2_K_MASK; + m = div64_u64((uint64_t)frac * ppm, 100000); + n = div64_u64((uint64_t)ppm * 65536 * fbdiv, 100000); + if (negative) { + fracdiv = frac + (div64_u64(m + n, 10)); + if (fracdiv > 32767) + return -EINVAL; + fracdiv = ~fracdiv + 1; + } else { + s = div64_u64(m + n, 10); + if (frac >= s) { + fracdiv = frac - s; + if (fracdiv > 32767) + return -EINVAL; + fracdiv = ~fracdiv + 1; + } else { + fracdiv = s - frac; + if (fracdiv > 32767) + return -EINVAL; + } + } + } else { + m = div64_u64((uint64_t)frac * ppm, 100000); + n = div64_u64((uint64_t)ppm * 65536 * fbdiv, 100000); + if (!negative) { + fracdiv = frac + (div64_u64(m + n, 10)); + if (fracdiv > 32767) + return -EINVAL; + } else { + s = div64_u64(m + n, 10); + if (frac >= s) { + fracdiv = frac - s; + if (fracdiv > 32767) + return -EINVAL; + } else { + fracdiv = s - frac; + if (fracdiv > 32767) + return -EINVAL; + fracdiv = ~fracdiv + 1; + } + } + } writel_relaxed(HIWORD_UPDATE(fracdiv, frac_mask, frac_shift), pll->reg_base + pllcon2); @@ -1772,6 +1876,7 @@ return mux_clk; err_pll: + kfree(pll->rate_table); clk_unregister(mux_clk); mux_clk = pll_clk; err_mux: -- Gitblit v1.6.2