+/*
+ * Find one solution to generate required frequency for SYSCLK
+ * out_freq: KHz, required frequency to the SYSCLK
+ * the result will be retuned with component RDW, VDW, OD, TTL,
+ * CLK2 and crystal
+ */
+unsigned long ics307_sysclk_calculator(unsigned long out_freq)
+{
+ const unsigned long input_freq = CONFIG_ICS307_REFCLK_HZ;
+ unsigned long vdw, rdw, odp, s_vdw = 0, s_rdw = 0, s_odp = 0, od;
+ unsigned long tmp_out, diff, result = 0;
+ int found = 0;
+
+ for (odp = 0; odp < NUM_OD_SETTING; odp++) {
+ od = ics307_s_to_od[odp];
+ if (od * out_freq < MIN_VCO || od * out_freq > MAX_VCO)
+ continue;
+ for (rdw = MIN_RDW; rdw <= MAX_RDW; rdw++) {
+ /* Calculate the VDW */
+ vdw = out_freq * 1000 * od * rdw / (input_freq * 2);
+ if (vdw > MAX_VDW)
+ vdw = MAX_VDW;
+ if (vdw < MIN_VDW)
+ continue;
+ /* Calculate the temp out frequency */
+ tmp_out = input_freq * 2 * vdw / (rdw * od * 1000);
+ diff = MAX(out_freq, tmp_out) - MIN(out_freq, tmp_out);
+ /*
+ * calculate the percent, the precision is 1/1000
+ * If greater than 1/1000, continue
+ * otherwise, we think the solution is we required
+ */
+ if (diff * 1000 / out_freq > 1)
+ continue;
+ else {
+ s_vdw = vdw;
+ s_rdw = rdw;
+ s_odp = odp;
+ found = 1;
+ break;
+ }
+ }
+ }
+
+ if (found)
+ result = (s_rdw - 2) | (s_vdw - 8) << 7 | s_odp << 16 |
+ CLK2 << 19 | TTL << 21 | CRYSTAL << 22;
+
+ debug("ICS307-02: RDW: %ld, VDW: %ld, OD: %d\n", s_rdw - 2, s_vdw - 8,
+ ics307_s_to_od[s_odp]);
+ return result;
+}
+