1 // SPDX-License-Identifier: GPL-2.0-only
3 * linux/arch/arm/common/icst307.c
5 * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved.
7 * Support functions for calculating clocks/divisors for the ICST307
8 * clock generators. See https://www.idt.com/ for more information
11 * This is an almost identical implementation to the ICST525 clock generator.
12 * The s2div and idx2s files are different
14 #include <linux/module.h>
15 #include <linux/kernel.h>
16 #include <asm/div64.h>
20 * Divisors for each OD setting.
22 const unsigned char icst307_s2div
[8] = { 10, 2, 8, 4, 5, 7, 3, 6 };
23 const unsigned char icst525_s2div
[8] = { 10, 2, 8, 4, 5, 7, 9, 6 };
24 EXPORT_SYMBOL(icst307_s2div
);
25 EXPORT_SYMBOL(icst525_s2div
);
27 unsigned long icst_hz(const struct icst_params
*p
, struct icst_vco vco
)
29 u64 dividend
= p
->ref
* 2 * (u64
)(vco
.v
+ 8);
30 u32 divisor
= (vco
.r
+ 2) * p
->s2div
[vco
.s
];
32 do_div(dividend
, divisor
);
33 return (unsigned long)dividend
;
36 EXPORT_SYMBOL(icst_hz
);
39 * Ascending divisor S values.
41 const unsigned char icst307_idx2s
[8] = { 1, 6, 3, 4, 7, 5, 2, 0 };
42 const unsigned char icst525_idx2s
[8] = { 1, 3, 4, 7, 5, 2, 6, 0 };
43 EXPORT_SYMBOL(icst307_idx2s
);
44 EXPORT_SYMBOL(icst525_idx2s
);
47 icst_hz_to_vco(const struct icst_params
*p
, unsigned long freq
)
49 struct icst_vco vco
= { .s
= 1, .v
= p
->vd_max
, .r
= p
->rd_max
};
51 unsigned int i
= 0, rd
, best
= (unsigned int)-1;
54 * First, find the PLL output divisor such
55 * that the PLL output is within spec.
58 f
= freq
* p
->s2div
[p
->idx2s
[i
]];
60 if (f
> p
->vco_min
&& f
<= p
->vco_max
)
71 * Now find the closest divisor combination
72 * which gives a PLL output of 'f'.
74 for (rd
= p
->rd_min
; rd
<= p
->rd_max
; rd
++) {
75 unsigned long fref_div
, f_pll
;
79 fref_div
= (2 * p
->ref
) / rd
;
81 vd
= (f
+ fref_div
/ 2) / fref_div
;
82 if (vd
< p
->vd_min
|| vd
> p
->vd_max
)
85 f_pll
= fref_div
* vd
;
90 if ((unsigned)f_diff
< best
) {
102 EXPORT_SYMBOL(icst_hz_to_vco
);