iio: frequency: ADF4350: Fix potential reference div factor overflow.
With small channel spacing values and high reference frequencies it is possible to exceed the range of the 10-bit counter. Workaround by checking the range and widening some constrains. We don't use the REG1_PHASE value in this case the datasheet recommends to set it to 1 if not used. Signed-off-by: Michael Hennerich <michael.hennerich@analog.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
This commit is contained in:
Родитель
dfffd0d65f
Коммит
8857df3ace
|
@ -129,7 +129,7 @@ static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq)
|
|||
{
|
||||
struct adf4350_platform_data *pdata = st->pdata;
|
||||
u64 tmp;
|
||||
u32 div_gcd, prescaler;
|
||||
u32 div_gcd, prescaler, chspc;
|
||||
u16 mdiv, r_cnt = 0;
|
||||
u8 band_sel_div;
|
||||
|
||||
|
@ -158,14 +158,20 @@ static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq)
|
|||
if (pdata->ref_div_factor)
|
||||
r_cnt = pdata->ref_div_factor - 1;
|
||||
|
||||
do {
|
||||
r_cnt = adf4350_tune_r_cnt(st, r_cnt);
|
||||
chspc = st->chspc;
|
||||
|
||||
st->r1_mod = st->fpfd / st->chspc;
|
||||
while (st->r1_mod > ADF4350_MAX_MODULUS) {
|
||||
r_cnt = adf4350_tune_r_cnt(st, r_cnt);
|
||||
st->r1_mod = st->fpfd / st->chspc;
|
||||
}
|
||||
do {
|
||||
do {
|
||||
do {
|
||||
r_cnt = adf4350_tune_r_cnt(st, r_cnt);
|
||||
st->r1_mod = st->fpfd / chspc;
|
||||
if (r_cnt > ADF4350_MAX_R_CNT) {
|
||||
/* try higher spacing values */
|
||||
chspc++;
|
||||
r_cnt = 0;
|
||||
}
|
||||
} while ((st->r1_mod > ADF4350_MAX_MODULUS) && r_cnt);
|
||||
} while (r_cnt == 0);
|
||||
|
||||
tmp = freq * (u64)st->r1_mod + (st->fpfd > 1);
|
||||
do_div(tmp, st->fpfd); /* Div round closest (n + d/2)/d */
|
||||
|
@ -194,7 +200,7 @@ static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq)
|
|||
st->regs[ADF4350_REG0] = ADF4350_REG0_INT(st->r0_int) |
|
||||
ADF4350_REG0_FRACT(st->r0_fract);
|
||||
|
||||
st->regs[ADF4350_REG1] = ADF4350_REG1_PHASE(0) |
|
||||
st->regs[ADF4350_REG1] = ADF4350_REG1_PHASE(1) |
|
||||
ADF4350_REG1_MOD(st->r1_mod) |
|
||||
prescaler;
|
||||
|
||||
|
|
|
@ -87,6 +87,8 @@
|
|||
#define ADF4350_MAX_BANDSEL_CLK 125000 /* Hz */
|
||||
#define ADF4350_MAX_FREQ_REFIN 250000000 /* Hz */
|
||||
#define ADF4350_MAX_MODULUS 4095
|
||||
#define ADF4350_MAX_R_CNT 1023
|
||||
|
||||
|
||||
/**
|
||||
* struct adf4350_platform_data - platform specific information
|
||||
|
|
Загрузка…
Ссылка в новой задаче