415 lines
6.8 KiB
C
Executable File
415 lines
6.8 KiB
C
Executable File
#include "cmucal.h"
|
|
#include "ra.h"
|
|
|
|
static struct pll_spec gpll1416X_spec = {
|
|
1, 63,
|
|
64, 1023,
|
|
0, 6,
|
|
0, 0,
|
|
4*MHZ, 12*MHZ,
|
|
1600*MHZ, 3200*MHZ,
|
|
200*MHZ, 3200*MHZ,
|
|
150, 0,
|
|
};
|
|
|
|
static struct pll_spec gpll1417X_spec = {
|
|
1, 63,
|
|
64, 1023,
|
|
0, 5,
|
|
0, 0,
|
|
4*MHZ, 12*MHZ,
|
|
1000*MHZ, 2000*MHZ,
|
|
200*MHZ, 2000*MHZ,
|
|
150, 0,
|
|
};
|
|
|
|
static struct pll_spec gpll1418X_spec = {
|
|
1, 63,
|
|
16, 511,
|
|
0, 5,
|
|
0, 0,
|
|
2*MHZ, 8*MHZ,
|
|
600*MHZ, 1200*MHZ,
|
|
100*MHZ, 1200*MHZ,
|
|
150, 0,
|
|
};
|
|
|
|
static struct pll_spec gpll1419X_spec = {
|
|
1, 63,
|
|
64, 1023,
|
|
0, 6,
|
|
0, 0,
|
|
4*MHZ, 12*MHZ,
|
|
1900*MHZ, 3800*MHZ,
|
|
200*MHZ, 3800*MHZ,
|
|
150, 0,
|
|
};
|
|
|
|
static struct pll_spec gpll1431X_spec = {
|
|
1, 63,
|
|
16, 511,
|
|
0, 5,
|
|
-32767, 32767,
|
|
6*MHZ, 30*MHZ,
|
|
400*MHZ, 800*MHZ,
|
|
50*MHZ, 800*MHZ,
|
|
150, 3000,
|
|
};
|
|
|
|
static struct pll_spec gpll1450X_spec = {
|
|
1, 63,
|
|
64, 1023,
|
|
0, 6,
|
|
0, 0,
|
|
4*MHZ, 12*MHZ,
|
|
1600*MHZ, 3304*MHZ,
|
|
25*MHZ, 3304*MHZ,
|
|
150, 0,
|
|
};
|
|
|
|
static struct pll_spec gpll1451X_spec = {
|
|
1, 63,
|
|
64, 1023,
|
|
0, 5,
|
|
0, 0,
|
|
4*MHZ, 12*MHZ,
|
|
900*MHZ, 1800*MHZ,
|
|
30*MHZ, 1800*MHZ,
|
|
150, 0,
|
|
};
|
|
|
|
static struct pll_spec gpll1452X_spec = {
|
|
1, 63,
|
|
16, 511,
|
|
0, 5,
|
|
0, 0,
|
|
4*MHZ, 8*MHZ,
|
|
500*MHZ, 1000*MHZ,
|
|
16*MHZ, 1000*MHZ,
|
|
150, 0,
|
|
};
|
|
|
|
static struct pll_spec gpll1460X_spec = {
|
|
1, 63,
|
|
16, 511,
|
|
0, 5,
|
|
-32767, 32767,
|
|
6*MHZ, 30*MHZ,
|
|
400*MHZ, 800*MHZ,
|
|
12.5*MHZ, 800*MHZ,
|
|
150, 3000,
|
|
};
|
|
|
|
static struct pll_spec gpll1050X_spec = {
|
|
1, 63,
|
|
64, 1023,
|
|
0, 6,
|
|
0, 0,
|
|
4*MHZ, 12*MHZ,
|
|
2250*MHZ, 4500*MHZ,
|
|
35.2*MHZ, 4500*MHZ,
|
|
150, 0,
|
|
};
|
|
|
|
static struct pll_spec gpll1051X_spec = {
|
|
1, 63,
|
|
64, 1023,
|
|
0, 6,
|
|
0, 0,
|
|
4*MHZ, 12*MHZ,
|
|
1200*MHZ, 2400*MHZ,
|
|
18.8*MHZ, 2400*MHZ,
|
|
150, 0,
|
|
};
|
|
|
|
static struct pll_spec gpll1052X_spec = {
|
|
1, 63,
|
|
64, 1023,
|
|
0, 6,
|
|
0, 0,
|
|
2*MHZ, 8*MHZ,
|
|
600*MHZ, 1200*MHZ,
|
|
9.5*MHZ, 1200*MHZ,
|
|
150, 0,
|
|
};
|
|
|
|
static struct pll_spec gpll1054X_spec = {
|
|
1, 63,
|
|
64, 1023,
|
|
0, 6,
|
|
0, 0,
|
|
4*MHZ, 12*MHZ,
|
|
1500*MHZ, 3000*MHZ,
|
|
23.4*MHZ, 3000*MHZ,
|
|
150, 0,
|
|
};
|
|
|
|
static struct pll_spec gpll1061X_spec = {
|
|
1, 63,
|
|
16, 511,
|
|
0, 6,
|
|
-32767, 32767,
|
|
6*MHZ, 30*MHZ,
|
|
600*MHZ, 1200*MHZ,
|
|
9.5*MHZ, 1200*MHZ,
|
|
150, 500,
|
|
};
|
|
|
|
static struct pll_spec gpll1016X_spec = {
|
|
1, 63,
|
|
64, 1023,
|
|
0, 6,
|
|
0, 0,
|
|
4.5*MHZ, 12*MHZ,
|
|
2250*MHZ, 4500*MHZ,
|
|
35.2*MHZ, 4500*MHZ,
|
|
150, 0,
|
|
};
|
|
|
|
static struct pll_spec gpll1017X_spec = {
|
|
1, 63,
|
|
64, 1023,
|
|
0, 6,
|
|
0, 0,
|
|
4*MHZ, 12*MHZ,
|
|
950*MHZ, 2400*MHZ,
|
|
18.8*MHZ, 2400*MHZ,
|
|
150, 0,
|
|
};
|
|
|
|
static struct pll_spec gpll1018X_spec = {
|
|
1, 63,
|
|
64, 1023,
|
|
0, 6,
|
|
0, 0,
|
|
2*MHZ, 8*MHZ,
|
|
600*MHZ, 1200*MHZ,
|
|
9.5*MHZ, 1200*MHZ,
|
|
150, 0,
|
|
};
|
|
|
|
static struct pll_spec gpll1019X_spec = {
|
|
1, 63,
|
|
64, 1023,
|
|
0, 6,
|
|
0, 0,
|
|
4*MHZ, 12*MHZ,
|
|
1500*MHZ, 3000*MHZ,
|
|
22.3*MHZ, 3000*MHZ,
|
|
150, 0,
|
|
};
|
|
|
|
static struct pll_spec gpll1031X_spec = {
|
|
1, 63,
|
|
16, 511,
|
|
0, 6,
|
|
-32767, 32767,
|
|
6*MHZ, 30*MHZ,
|
|
600*MHZ, 1200*MHZ,
|
|
9.5*MHZ, 1200*MHZ,
|
|
150, 500,
|
|
};
|
|
|
|
struct pll_spec *pll_get_spec(struct cmucal_pll *pll)
|
|
{
|
|
struct pll_spec *pll_spec;
|
|
|
|
switch (pll->type) {
|
|
case PLL_1416X:
|
|
pll_spec = &gpll1416X_spec;
|
|
break;
|
|
case PLL_1417X:
|
|
pll_spec = &gpll1417X_spec;
|
|
break;
|
|
case PLL_1418X:
|
|
pll_spec = &gpll1418X_spec;
|
|
break;
|
|
case PLL_1419X:
|
|
pll_spec = &gpll1419X_spec;
|
|
break;
|
|
case PLL_1431X:
|
|
pll_spec = &gpll1431X_spec;
|
|
break;
|
|
case PLL_1450X:
|
|
pll_spec = &gpll1450X_spec;
|
|
break;
|
|
case PLL_1451X:
|
|
pll_spec = &gpll1451X_spec;
|
|
break;
|
|
case PLL_1452X:
|
|
pll_spec = &gpll1452X_spec;
|
|
break;
|
|
case PLL_1460X:
|
|
pll_spec = &gpll1460X_spec;
|
|
break;
|
|
case PLL_1050X:
|
|
pll_spec = &gpll1050X_spec;
|
|
break;
|
|
case PLL_1051X:
|
|
pll_spec = &gpll1051X_spec;
|
|
break;
|
|
case PLL_1052X:
|
|
pll_spec = &gpll1052X_spec;
|
|
break;
|
|
case PLL_1054X:
|
|
pll_spec = &gpll1054X_spec;
|
|
break;
|
|
case PLL_1061X:
|
|
pll_spec = &gpll1061X_spec;
|
|
break;
|
|
case PLL_1016X:
|
|
pll_spec = &gpll1016X_spec;
|
|
break;
|
|
case PLL_1017X:
|
|
pll_spec = &gpll1017X_spec;
|
|
break;
|
|
case PLL_1018X:
|
|
pll_spec = &gpll1018X_spec;
|
|
break;
|
|
case PLL_1019X:
|
|
pll_spec = &gpll1019X_spec;
|
|
break;
|
|
case PLL_1031X:
|
|
pll_spec = &gpll1031X_spec;
|
|
break;
|
|
default:
|
|
pll_spec = NULL;
|
|
}
|
|
|
|
return pll_spec;
|
|
}
|
|
|
|
static unsigned int __pll_find_m(unsigned int p, unsigned int s,
|
|
unsigned long long fin,
|
|
unsigned long long rate)
|
|
{
|
|
rate *= p << s;
|
|
do_div(rate, fin);
|
|
|
|
return rate;
|
|
}
|
|
|
|
static int __pll_find_k(unsigned int p, unsigned int m, unsigned int s,
|
|
unsigned long long fin,
|
|
unsigned long long rate)
|
|
{
|
|
rate <<= 16;
|
|
rate *= p << s;
|
|
do_div(rate, fin);
|
|
|
|
return rate - (m << 16);
|
|
}
|
|
|
|
int pll_get_locktime(struct cmucal_pll *pll)
|
|
{
|
|
struct pll_spec *pll_spec;
|
|
|
|
pll_spec = pll_get_spec(pll);
|
|
if (!pll_spec) {
|
|
pr_err("un-support pll type\n");
|
|
return -EVCLKINVAL;
|
|
}
|
|
|
|
pll->lock_time = pll_spec->lock_time;
|
|
pll->flock_time = pll_spec->flock_time;
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(pll_get_locktime);
|
|
|
|
int pll_find_table(struct cmucal_pll *pll,
|
|
struct cmucal_pll_table *table,
|
|
unsigned long long fin,
|
|
unsigned long long rate)
|
|
{
|
|
struct pll_spec *pll_spec;
|
|
unsigned int p, m, s;
|
|
int k;
|
|
unsigned long long fref, fvco, fout;
|
|
unsigned long long min_diff = 0, tmp;
|
|
unsigned int min_p, min_m, min_s, min_fout;
|
|
|
|
pll_spec = pll_get_spec(pll);
|
|
if (!pll_spec) {
|
|
pr_err("un-support pll type\n");
|
|
return -EVCLKINVAL;
|
|
}
|
|
|
|
/* khz_to_hz() : for calculate precisely */
|
|
rate = khz_to_hz(rate);
|
|
|
|
for (p = pll_spec->pdiv_min; p <= pll_spec->pdiv_max; p++) {
|
|
/* check fref */
|
|
fref = fin / p;
|
|
if ((fref < pll_spec->fref_min) || (fref > pll_spec->fref_max))
|
|
continue;
|
|
for (s = pll_spec->sdiv_min; s <= pll_spec->sdiv_max; s++) {
|
|
/* check m value */
|
|
m = __pll_find_m(p, s, fin, rate);
|
|
if ((m < pll_spec->mdiv_min) ||
|
|
(m > pll_spec->mdiv_max))
|
|
continue;
|
|
|
|
if (is_normal_pll(pll)) {
|
|
k = 0;
|
|
fvco = fin * m;
|
|
} else {
|
|
/* check k value */
|
|
k = __pll_find_k(p, m, s, fin, rate);
|
|
if ((k < pll_spec->kdiv_min) ||
|
|
(k > pll_spec->kdiv_max))
|
|
continue;
|
|
|
|
fvco = fin * ((m << 16) + k);
|
|
fvco >>= 16;
|
|
}
|
|
|
|
/* check fvco */
|
|
do_div(fvco, p);
|
|
if ((fvco < pll_spec->fvco_min) ||
|
|
(fvco > pll_spec->fvco_max))
|
|
continue;
|
|
|
|
/* check fout */
|
|
fout = fvco >> s;
|
|
if ((fout >= pll_spec->fout_min) &&
|
|
(fout <= pll_spec->fout_max)) {
|
|
/* hz_to_khz() : to change resolution */
|
|
if (hz_to_khz(rate) == hz_to_khz(fout)) {
|
|
table->rate = fout;
|
|
table->pdiv = p;
|
|
table->mdiv = m;
|
|
table->sdiv = s;
|
|
table->kdiv = k;
|
|
|
|
return 0;
|
|
}
|
|
|
|
if (is_normal_pll(pll)) {
|
|
tmp = abs(rate - fout);
|
|
if (min_diff == 0 || tmp < min_diff) {
|
|
min_diff = tmp;
|
|
min_fout = fout;
|
|
min_p = p;
|
|
min_m = m;
|
|
min_s = s;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (min_diff) {
|
|
table->rate = min_fout;
|
|
table->pdiv = min_p;
|
|
table->mdiv = min_m;
|
|
table->sdiv = min_s;
|
|
table->kdiv = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
return -EVCLKINVAL;
|
|
}
|
|
EXPORT_SYMBOL_GPL(pll_find_table);
|