From a5969cabbb4660eab42b6ef0412cbbd1200cf14d Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Sat, 12 Oct 2024 07:10:09 +0000
Subject: [PATCH] 修改led为gpio
---
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